|
|
@@ -0,0 +1,114 @@
|
|
|
+<template>
|
|
|
+ <div :style="styleMap?.mainStyle" class="relative w-full h-full box-border overflow-hidden">
|
|
|
+ <ImageBg
|
|
|
+ v-if="styleMap?.mainStyle?.imageSrc"
|
|
|
+ :src="styleMap?.mainStyle?.imageSrc"
|
|
|
+ :imageStyle="styleMap?.mainStyle?.imageStyle"
|
|
|
+ />
|
|
|
+
|
|
|
+ <svg class="absolute inset-0 w-full h-full block" :viewBox="viewBox" xmlns="http://www.w3.org/2000/svg">
|
|
|
+ <path
|
|
|
+ v-if="shapeMode && fillPath"
|
|
|
+ :d="fillPath"
|
|
|
+ :fill="styleMap?.itemsStyle?.backgroundColor || '#ffffffff'"
|
|
|
+ />
|
|
|
+ <path
|
|
|
+ v-for="(path, index) in strokePaths"
|
|
|
+ :key="index"
|
|
|
+ :d="path"
|
|
|
+ fill="none"
|
|
|
+ :stroke="styleMap?.mainStyle?.line?.color || '#212121ff'"
|
|
|
+ :stroke-width="strokeWidth"
|
|
|
+ :stroke-linecap="styleMap?.mainStyle?.line?.radius ? 'round' : 'butt'"
|
|
|
+ stroke-linejoin="round"
|
|
|
+ :stroke-dasharray="dashArray"
|
|
|
+ />
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { computed } from 'vue'
|
|
|
+import { useWidgetStyle } from '../hooks/useWidgetStyle'
|
|
|
+import { useProjectStore } from '@/store/modules/project'
|
|
|
+import ImageBg from '../ImageBg.vue'
|
|
|
+
|
|
|
+const props = defineProps<{
|
|
|
+ width: number
|
|
|
+ height: number
|
|
|
+ styles: any
|
|
|
+ state?: string
|
|
|
+ part?: string
|
|
|
+ shapeMode?: boolean
|
|
|
+ path: {
|
|
|
+ source: 'resource' | 'custom'
|
|
|
+ resourceId: string
|
|
|
+ segments: {
|
|
|
+ start: { x: number; y: number }
|
|
|
+ control1: { x: number; y: number }
|
|
|
+ control2: { x: number; y: number }
|
|
|
+ end: { x: number; y: number }
|
|
|
+ }[]
|
|
|
+ }
|
|
|
+}>()
|
|
|
+
|
|
|
+const styleMap = useWidgetStyle({
|
|
|
+ widget: 'lv_bezier',
|
|
|
+ props
|
|
|
+})
|
|
|
+const projectStore = useProjectStore()
|
|
|
+
|
|
|
+const viewBox = computed(() => `0 0 ${props.width} ${props.height}`)
|
|
|
+const strokeWidth = computed(() => styleMap.value?.mainStyle?.line?.width ?? 5)
|
|
|
+const dashArray = computed(() => {
|
|
|
+ const line = styleMap.value?.mainStyle?.line
|
|
|
+ const dashWidth = Number(line?.dashWidth || 0)
|
|
|
+ const dashGap = Number(line?.dashGap || 0)
|
|
|
+ return dashWidth > 0 ? `${dashWidth} ${dashGap || dashWidth}` : undefined
|
|
|
+})
|
|
|
+
|
|
|
+const segments = computed(() => {
|
|
|
+ if (props.path?.source === 'resource') {
|
|
|
+ return (
|
|
|
+ projectStore.project?.resources.bezierAnimations.find(
|
|
|
+ (item) => item.id === props.path.resourceId
|
|
|
+ )?.segments || props.path?.segments || []
|
|
|
+ )
|
|
|
+ }
|
|
|
+ return props.path?.segments || []
|
|
|
+})
|
|
|
+
|
|
|
+const buildSegmentPath = (segment: any) => {
|
|
|
+ return `M ${segment.start.x} ${segment.start.y} C ${segment.control1.x} ${segment.control1.y}, ${segment.control2.x} ${segment.control2.y}, ${segment.end.x} ${segment.end.y}`
|
|
|
+}
|
|
|
+
|
|
|
+const strokePaths = computed(() => {
|
|
|
+ const list = segments.value.map(buildSegmentPath)
|
|
|
+ if (!props.shapeMode || !segments.value.length) return list
|
|
|
+
|
|
|
+ const first = segments.value[0]
|
|
|
+ const result = [...list]
|
|
|
+ for (let i = 0; i < segments.value.length - 1; i += 1) {
|
|
|
+ const current = segments.value[i]
|
|
|
+ const next = segments.value[i + 1]
|
|
|
+ result.push(`M ${current.end.x} ${current.end.y} L ${next.start.x} ${next.start.y}`)
|
|
|
+ }
|
|
|
+ const last = segments.value[segments.value.length - 1]
|
|
|
+ result.push(`M ${last.end.x} ${last.end.y} L ${first.start.x} ${first.start.y}`)
|
|
|
+ return result
|
|
|
+})
|
|
|
+
|
|
|
+const fillPath = computed(() => {
|
|
|
+ if (!props.shapeMode || !segments.value.length) return ''
|
|
|
+ const first = segments.value[0]
|
|
|
+ const parts = [`M ${first.start.x} ${first.start.y}`]
|
|
|
+ segments.value.forEach((segment) => {
|
|
|
+ parts.push(`C ${segment.control1.x} ${segment.control1.y}, ${segment.control2.x} ${segment.control2.y}, ${segment.end.x} ${segment.end.y}`)
|
|
|
+ })
|
|
|
+ for (let i = 0; i < segments.value.length - 1; i += 1) {
|
|
|
+ parts.push(`L ${segments.value[i + 1].start.x} ${segments.value[i + 1].start.y}`)
|
|
|
+ }
|
|
|
+ parts.push(`L ${first.start.x} ${first.start.y} Z`)
|
|
|
+ return parts.join(' ')
|
|
|
+})
|
|
|
+</script>
|