update 自定义飞线组件
parent
4ac6bae1e2
commit
3d4abe7a19
@ -0,0 +1,135 @@
|
|||||||
|
<template>
|
||||||
|
<svg
|
||||||
|
:viewBox="`0 0 ${props.width} ${props.height}`"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<g v-for="(line, index) in lines" :key="index">
|
||||||
|
<!-- 定义阴影滤镜 -->
|
||||||
|
<defs>
|
||||||
|
<filter
|
||||||
|
v-if="line.am && line.dot"
|
||||||
|
:id="`shadow-${uid}-${index}`"
|
||||||
|
x="-200%"
|
||||||
|
y="-200%"
|
||||||
|
width="500%"
|
||||||
|
height="500%"
|
||||||
|
>
|
||||||
|
<feDropShadow
|
||||||
|
dx="0"
|
||||||
|
dy="0"
|
||||||
|
:stdDeviation="1"
|
||||||
|
:flood-color="line.flyingColor"
|
||||||
|
flood-opacity="1"
|
||||||
|
/>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<!-- 定义线性渐变 -->
|
||||||
|
<linearGradient
|
||||||
|
v-if="line.am && line.flying"
|
||||||
|
:id="`gradient-${uid}-${index}`"
|
||||||
|
x1="0%"
|
||||||
|
y1="0%"
|
||||||
|
x2="100%"
|
||||||
|
y2="0%"
|
||||||
|
>
|
||||||
|
<stop offset="0%" style="stop-color: black; stop-opacity: 1" />
|
||||||
|
<stop offset="100%" style="stop-color: white; stop-opacity: 1" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- 定义mask -->
|
||||||
|
<mask :id="`mask-${uid}-${index}`" v-if="line.am && line.flying">
|
||||||
|
<rect
|
||||||
|
:x="-line.flyingLen"
|
||||||
|
:y="-line.size"
|
||||||
|
:width="line.flyingLen"
|
||||||
|
:height="line.size * 3"
|
||||||
|
:fill="`url(#gradient-${uid}-${index})`"
|
||||||
|
>
|
||||||
|
<animateMotion
|
||||||
|
:dur="line.time"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
rotate="auto"
|
||||||
|
>
|
||||||
|
<mpath :href="`#bezierPath-${uid}-${index}`" />
|
||||||
|
</animateMotion>
|
||||||
|
</rect>
|
||||||
|
</mask>
|
||||||
|
</defs>
|
||||||
|
<!-- 定义二次贝塞尔曲线路径 -->
|
||||||
|
<path
|
||||||
|
:id="`bezierPath-${uid}-${index}`"
|
||||||
|
:d="line.path"
|
||||||
|
:stroke-width="line.size"
|
||||||
|
:stroke="line.lineColor"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
fill="none"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
v-if="line.am && line.flying"
|
||||||
|
:d="line.path"
|
||||||
|
:stroke-width="line.size"
|
||||||
|
:stroke="line.flyingColor"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
fill="none"
|
||||||
|
:mask="`url(#mask-${uid}-${index})`"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 定义光点 -->
|
||||||
|
<circle
|
||||||
|
v-if="line.am && line.dot"
|
||||||
|
cx="0"
|
||||||
|
cy="0"
|
||||||
|
:r="(line.size / 5) * 3"
|
||||||
|
:fill="line.flyingColor"
|
||||||
|
:filter="`url(#shadow-${uid}-${index})`"
|
||||||
|
>
|
||||||
|
<!-- 使用animateMotion让光点沿路径移动 -->
|
||||||
|
<animateMotion
|
||||||
|
:dur="line.time"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
calcMode="linear"
|
||||||
|
>
|
||||||
|
<mpath :href="`#bezierPath-${uid}-${index}`" rotate="reverse" />
|
||||||
|
</animateMotion>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { IdGenerator } from "@/util";
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
//唯一标识
|
||||||
|
const uid = IdGenerator.next();
|
||||||
|
|
||||||
|
const defineLine = {
|
||||||
|
path: `M 10,10 C 200,10,10,200,290,290`,
|
||||||
|
size: 1,
|
||||||
|
lineColor: "var(--w-bg-dark)",
|
||||||
|
flyingColor: "var(--w-main)",
|
||||||
|
flyingLen: 20,
|
||||||
|
flying: true,
|
||||||
|
dot: true,
|
||||||
|
am: true,
|
||||||
|
time: "5s",
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
width: { type: Number, default: 300 },
|
||||||
|
height: { type: Number, default: 300 },
|
||||||
|
lines: { type: Array, default: [] },
|
||||||
|
});
|
||||||
|
|
||||||
|
const lines = computed(()=>{
|
||||||
|
return props.lines.map((line) => {
|
||||||
|
return {
|
||||||
|
...defineLine,
|
||||||
|
...line,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
class IdGenerator {
|
||||||
|
static #idGenerator = new IdGenerator();
|
||||||
|
|
||||||
|
#count = 0;
|
||||||
|
|
||||||
|
#countGen() {
|
||||||
|
this.#count++;
|
||||||
|
if (this.#count >= 1296) {
|
||||||
|
this.#count = 0;
|
||||||
|
}
|
||||||
|
return this.#count.toString(36).padEnd(2, "0");
|
||||||
|
}
|
||||||
|
next() {
|
||||||
|
return (
|
||||||
|
Date.now().toString(36) +
|
||||||
|
this.#countGen() +
|
||||||
|
Math.random().toString(36).substring(2, 10)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static next() {
|
||||||
|
return IdGenerator.#idGenerator.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { IdGenerator }
|
||||||
Loading…
Reference in New Issue