96 lines
2.7 KiB
Vue
96 lines
2.7 KiB
Vue
<script lang="ts" setup>
|
|
import { useVueFlow } from '@vue-flow/core'
|
|
import { computed, toRef } from 'vue'
|
|
import { BackgroundVariant } from './types'
|
|
import type { BackgroundProps } from './types'
|
|
import { DefaultBgColors, DotPattern, LinePattern } from './patterns'
|
|
|
|
const {
|
|
id,
|
|
variant = BackgroundVariant.Dots,
|
|
gap = 20,
|
|
size = 1,
|
|
lineWidth = 1,
|
|
height = 100,
|
|
width = 100,
|
|
x = 0,
|
|
y = 0,
|
|
bgColor,
|
|
patternColor: initialPatternColor,
|
|
offset = 2,
|
|
} = defineProps<BackgroundProps>()
|
|
|
|
const { id: vueFlowId, viewport } = useVueFlow()
|
|
|
|
const background = computed(() => {
|
|
const [gapX, gapY] = Array.isArray(gap) ? gap : [gap, gap]
|
|
|
|
const scaledGap: [number, number] = [gapX * viewport.value.zoom || 1, gapY * viewport.value.zoom || 1]
|
|
|
|
const scaledSize = size * viewport.value.zoom
|
|
|
|
const patternOffset =
|
|
variant === BackgroundVariant.Dots
|
|
? [scaledSize / offset, scaledSize / offset]
|
|
: [scaledGap[0] / offset, scaledGap[1] / offset]
|
|
|
|
return {
|
|
scaledGap,
|
|
offset: patternOffset,
|
|
size: scaledSize,
|
|
}
|
|
})
|
|
|
|
// when there are multiple flows on a page we need to make sure that every background gets its own pattern.
|
|
const patternId = toRef(() => `pattern-${vueFlowId}${id ? `-${id}` : ''}`)
|
|
|
|
const patternColor = toRef(() => initialPatternColor || DefaultBgColors[variant || BackgroundVariant.Dots])
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
export default {
|
|
name: 'Background',
|
|
compatConfig: { MODE: 3 },
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<svg
|
|
class="vue-flow__background vue-flow__container"
|
|
:style="{
|
|
height: `${height > 100 ? 100 : height}%`,
|
|
width: `${width > 100 ? 100 : width}%`,
|
|
}"
|
|
>
|
|
<slot :id="patternId" name="pattern-container">
|
|
<pattern
|
|
:id="patternId"
|
|
:x="viewport.x % background.scaledGap[0]"
|
|
:y="viewport.y % background.scaledGap[1]"
|
|
:width="background.scaledGap[0]"
|
|
:height="background.scaledGap[1]"
|
|
:patternTransform="`translate(-${background.offset[0]},-${background.offset[1]})`"
|
|
patternUnits="userSpaceOnUse"
|
|
>
|
|
<slot name="pattern">
|
|
<template v-if="variant === BackgroundVariant.Lines">
|
|
<LinePattern :size="lineWidth" :color="patternColor" :dimensions="background.scaledGap" />
|
|
</template>
|
|
|
|
<template v-else-if="variant === BackgroundVariant.Dots">
|
|
<DotPattern :color="patternColor" :radius="background.size / offset" />
|
|
</template>
|
|
|
|
<svg v-if="bgColor" height="100" width="100">
|
|
<rect width="100%" height="100%" :fill="bgColor" />
|
|
</svg>
|
|
</slot>
|
|
</pattern>
|
|
</slot>
|
|
|
|
<rect :x="x" :y="y" width="100%" height="100%" :fill="`url(#${patternId})`" />
|
|
|
|
<slot :id="patternId" />
|
|
</svg>
|
|
</template>
|