Vue3实现艺术字组件,包含阴影和描边

<!-- 艺术字组件,实现描边和阴影 -->
<script setup lang="ts">
import { computed } from 'vue'

interface IProps {
  strokeColor?: string
  strokeGradient?: string
  strokeWidth?: number | string
  showStroke?: boolean
  color?: string
  gradient?: string
  shadowColor?: string
  shadowGradient?: string
  shadowX?: number | string
  shadowY?: number | string
}

const props = withDefaults(defineProps<IProps>(), {
  showStroke: true,
  shadowX: 0,
  shadowY: 0,
})

const formatPxToVw = px => {
  return typeof px === 'number' ? `${px / 7.5}vw` : px
}

const computedStrokeWidth = computed(() => formatPxToVw(props.strokeWidth))

const computedShadowX = computed(() => formatPxToVw(props.shadowX))

const computedShadowY = computed(() => formatPxToVw(props.shadowY))

const strokeColorStyle = computed(() => {
  if (props.strokeGradient) {
    return {
      'background-image': props.strokeGradient,
      '-webkit-text-fill-color': 'transparent',
      '-webkit-text-stroke': `transparent ${computedStrokeWidth.value}`,
    }
  }

  return {
    color: props.strokeColor,
    '-webkit-text-stroke': `${props.strokeColor} ${computedStrokeWidth.value}`,
  }
})

const colorStyle = computed(() => {
  if (props.gradient) {
    return {
      'background-image': props.gradient,
      '-webkit-text-fill-color': 'transparent',
    }
  }

  if (props.color) {
    return {
      color: props.color,
    }
  }

  return {}
})

const shadowColorStyle = computed(() => {
  if (props.shadowGradient) {
    return {
      'background-image': props.shadowGradient,
      '-webkit-text-fill-color': 'transparent',
      '-webkit-text-stroke': `transparent ${computedStrokeWidth.value}`,
    }
  }

  return {
    color: props.shadowColor,
    '-webkit-text-stroke': `${props.shadowColor} ${computedStrokeWidth.value}`,
  }
})
</script>
<template>
  <div class="word-art">
    <div
      v-if="showStroke"
      class="text-shadow"
      :style="{
        ...shadowColorStyle,
        top: computedShadowY,
        left: computedShadowX,
      }"
    >
      <slot></slot>
    </div>
    <div
      v-if="showStroke"
      class="text-stroke"
      :style="{
        ...strokeColorStyle,
      }"
    >
      <slot></slot>
    </div>
    <div class="text-draw" :style="{ ...colorStyle }">
      <slot></slot>
    </div>
  </div>
</template>

<style lang="less" scoped>
.word-art {
  position: relative;
}

.text-shadow {
  stroke-linecap: butt;
  stroke-linejoin: round;
  position: absolute;
  left: 0;
  right: 0;
  background-clip: text;
  -webkit-background-clip: text;
  background-size: 100% 100%;
}

.text-stroke {
  stroke-linecap: butt;
  stroke-linejoin: round;
  position: absolute;
  left: 0;
  right: 0;
  background-clip: text;
  -webkit-background-clip: text;
  background-size: 100% 100%;
}

.text-draw {
  position: relative;
  background-clip: text;
  -webkit-background-clip: text;
  background-size: 100% 100%;
}
</style>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值