Vue3实现印章徽章组件

1、组件结构

2、组件封装

src/components/StampBadge/src/StampBadge.vue 文件代码

<template>
    <div
      class="first-ring"
      v-bind="getBindValue"
      :class="getStampBadgeClass"
    >
      <div class="second-ring" :class="getStampBadgeClass">
      <div class="third-ring" :class="getStampBadgeClass">
      <div class="forth-ring" :class="getStampBadgeClass">
      <div class="content-rectangle ellipsis" :class="getStampBadgeClass">
        <span class="">{{content}}</span>
      </div>
      </div>
      </div>
      </div>
    </div>
  </template>
  
  <script lang="ts">
    import { defineComponent } from "vue";
    export default defineComponent({
      name: "StampBadge",
      inheritAttrs: false,
    });
  </script>
  
  <script lang="ts" setup>
    import { computed, onMounted, unref } from "vue";
    import { stampBadgeProps } from "./props";
    // import { useAttrs } from "/@/hooks/core/useAttrs";

    const props = defineProps(stampBadgeProps);
    // get component class
    // const attrs = useAttrs({ excludeDefaultKeys: false });
    const getStampBadgeClass = computed(() => {
      const { color, size } = props;
      return [
      {
      [`stamp-badge-${color}`]: !!color,
      [`stamp-badge-${size}`]: !!size,
      },
      ];
    });
    onMounted(() => {
      rotate()
    });
    async function rotate() {
      const { rotate ,opacity} = props;
      var element = document.getElementsByClassName('first-ring')[0]; // 获取你想要旋转的元素
      element.style.webkitTransform = 'rotate('+ rotate +'deg)'; // Chrome, Safari 和 Opera
      element.style.msTransform = 'rotate('+ rotate +'deg)'; // 旧版的IE
      element.style.transform = 'rotate('+ rotate +'deg)'; // 标准语法
      element.style.opacity = opacity;
    };
  
    // get inherit binding value
    // const getBindValue = computed(() => ({ ...unref(attrs), ...props }));
    const getBindValue = computed(() => ({  ...props }));
  </script>
  
  <style lang="less" scoped>
    .first-ring {
      display: flex;
      align-items: center;
      justify-content: center;
      
      /* 生成的图片是有一张,开启repeat自动填充 */
      pointer-events: none;
      background: repeat;
      border-radius: 100px;

      /* 核心部分,决定水印层与内容部分的结合方式 */
      mix-blend-mode: multiply;
    }
  
    .second-ring {
      display: flex;
      align-items: center;
      justify-content: center;
      background: #fff;
      border-radius: 100px;
    }
  
    .third-ring {
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 100px;
    }
  
    .forth-ring {
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;
      background: #fff;
      border-radius: 100px;
    }
  
    .content-rectangle {
      position: absolute;
      font-weight: bold;
      text-align: center;
      background: #fff;
    }
  
    .ellipsis {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  
    // primary
    .stamp-badge-primary.first-ring {
      background: #1890ff;
    }

    .stamp-badge-primary.third-ring {
      background: #1890ff;
    }

    .stamp-badge-primary.content-rectangle {
      color: #1890ff;
      border: 1px solid #1890ff;
    }
    // success
    .stamp-badge-success.first-ring {
      background: #52c41a;
    }

    .stamp-badge-success.third-ring {
      background: #52c41a;
    }

    .stamp-badge-success.content-rectangle {
      color: #52c41a;
      border: 1px solid #52c41a;
    }
    // error
    .stamp-badge-error.first-ring {
      background: #ff4d4f;
    }

    .stamp-badge-error.third-ring {
      background: #ff4d4f;
    }

    .stamp-badge-error.content-rectangle {
      color: #ff4d4f;
      border: 1px solid #ff4d4f;
    }
    // warning
    .stamp-badge-warning.first-ring {
      background: #faad14;
    }

    .stamp-badge-warning.third-ring {
      background: #faad14;
    }

    .stamp-badge-warning.content-rectangle {
      color: #faad14;
      border: 1px solid #faad14;
    }
    // info
    .stamp-badge-info.first-ring {
      background: #ccc;
    }

    .stamp-badge-info.third-ring {
      background: #ccc;
    }

    .stamp-badge-info.content-rectangle {
      color: #ccc;
      border: 1px solid #ccc;
    }
    // large
    .stamp-badge-large.first-ring {
      width: 84px;
      height: 84px;
    }

    .stamp-badge-large.second-ring {
      width: 80px;
      height: 80px;
    }

    .stamp-badge-large.third-ring {
      width: 74px;
      height: 74px;
    }

    .stamp-badge-large.forth-ring {
      width: 64px;
      height: 64px;
    }

    .stamp-badge-large.content-rectangle {
      width: 90px;
      font-size: 1.2rem;
    }
    // middle
    .stamp-badge-middle.first-ring {
      width: 64px;
      height: 64px;
    }

    .stamp-badge-middle.second-ring {
      width: 60px;
      height: 60px;
    }

    .stamp-badge-middle.third-ring {
      width: 56px;
      height: 56px;
    }

    .stamp-badge-middle.forth-ring {
      width: 48px;
      height: 48px;
    }

    .stamp-badge-middle.content-rectangle {
      width: 70px;
      font-size: 1rem;
    }
    // small
    .stamp-badge-small.first-ring {
      width: 54px;
      height: 54px;
    }

    .stamp-badge-small.second-ring {
      width: 50px;
      height: 50px;
    }

    .stamp-badge-small.third-ring {
      width: 46px;
      height: 46px;
    }

    .stamp-badge-small.forth-ring {
      width: 38px;
      height: 38px;
    }

    .stamp-badge-small.content-rectangle {
      width: 60px;
      font-size: 0.8rem;
    }
    // auto
    .stamp-badge-auto.first-ring {
      width: 100%;
      height: 100%;
    }

    .stamp-badge-auto.second-ring {
      width: 80%;
      height: 80%;
    }

    .stamp-badge-auto.third-ring {
      width: 80%;
      height: 80%;
    }

    .stamp-badge-auto.forth-ring {
      width: 80%;
      height: 80%;
    }

    .stamp-badge-auto.content-rectangle {
      width: 80%;
      font-size: 80%;
      border-width:0.3rem;
    }
  </style>

src/components/StampBadge/src/props.ts 文件代码

export const stampBadgeProps = {
  color: {
    type: String,
    default: "primary",
    validator: (v) =>
      ["primary", "error", "warning", "success", "info"].includes(v),
  },
  /**
   * stamp badge size.
   * @default: middle
   */
  size: {
    type: String,
    default: "middle",
    validator: (v) => ["large", "middle", "small", "auto"].includes(v),
  },
  /**
   * stamp badge rotate deg.
   * @default: 0
   */
  rotate: { type: Number, default: 0 },
  opacity: { type: Number, default: 1 },
  content: { type: String, default: "Unknown" },
};

src/components/StampBadge/index.ts 文件代码

import { withInstall } from "@/utils/StamoBadge";
import type { ExtractPropTypes } from "vue";
import stampbadge from "./src/StampBadge.vue";
import { stampBadgeProps } from "./src/props";

export const StampBadge = withInstall(stampbadge);
export declare type ButtonProps = Partial<
  ExtractPropTypes<typeof stampBadgeProps>
>;

src/utils/index.ts 文件代码

export const withInstall = <T>(component: T, alias?: string) => {
  const comp = component as any;
  comp.install = (app: App) => {
    app.component(comp.name || comp.displayName, component);
    if (alias) {
      app.config.globalProperties[alias] = component;
    }
  };
  return component as T & Plugin;
};

3、组件应用

···



posted @ 2024-08-09 16:04  seekHelp  阅读(52)  评论(0编辑  收藏  举报