mirror of
https://git.hmsn.ink/kospo/svcm/oa.git
synced 2026-03-20 08:03:34 +09:00
106 lines
2.1 KiB
Vue
106 lines
2.1 KiB
Vue
<script setup lang="ts">
|
|
import type { PeityOptions, PeityType } from '/@src/utils/peity/types'
|
|
import { drawBar, drawLine, drawPie } from '/@src/utils/peity'
|
|
|
|
export interface VPeityProps {
|
|
values: number[]
|
|
type: PeityType
|
|
min?: number
|
|
max?: number
|
|
radius?: number
|
|
innerRadius?: number
|
|
height?: number
|
|
width?: number
|
|
padding?: number
|
|
stroke?: string
|
|
strokeWidth?: number
|
|
fill?: string[]
|
|
}
|
|
|
|
const props = withDefaults(defineProps<VPeityProps>(), {
|
|
type: 'line',
|
|
radius: 8,
|
|
padding: 0.1,
|
|
innerRadius: 5,
|
|
min: undefined,
|
|
max: undefined,
|
|
height: 16,
|
|
width: 16,
|
|
stroke: undefined,
|
|
strokeWidth: 1,
|
|
fill: undefined,
|
|
values: () => [],
|
|
})
|
|
|
|
const svgElement = ref<HTMLElement>()
|
|
const svgHeight = computed(() => {
|
|
const height = props.height || 16
|
|
|
|
if (props.type === 'pie' || props.type === 'donut') {
|
|
const diameter = props.radius * 2
|
|
return height || diameter
|
|
}
|
|
|
|
return height
|
|
})
|
|
const svgWidth = computed(() => {
|
|
const width = props.width || 16
|
|
|
|
if (props.type === 'pie' || props.type === 'donut') {
|
|
const diameter = props.radius * 2
|
|
return width || diameter
|
|
}
|
|
|
|
return width
|
|
})
|
|
|
|
watchPostEffect(() => {
|
|
if (!svgElement.value) {
|
|
return
|
|
}
|
|
|
|
const element = svgElement.value
|
|
element.innerHTML = ''
|
|
|
|
const opts: PeityOptions = {
|
|
type: props.type,
|
|
height: props.height,
|
|
width: props.width,
|
|
fill: (idx: number): string => {
|
|
const f = props.fill ?? []
|
|
return f[idx % f.length]
|
|
},
|
|
}
|
|
|
|
switch (props.type) {
|
|
case 'bar':
|
|
opts.min = props.min
|
|
opts.padding = props.padding
|
|
drawBar(element, props.values, opts)
|
|
break
|
|
case 'line':
|
|
opts.min = props.min
|
|
opts.stroke = props.stroke
|
|
opts.strokeWidth = props.strokeWidth
|
|
drawLine(element, props.values, opts)
|
|
break
|
|
case 'pie':
|
|
case 'donut':
|
|
opts.radius = props.radius
|
|
opts.innerRadius = props.innerRadius
|
|
drawPie(element, props.values, opts)
|
|
break
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<svg
|
|
ref="svgElement"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
class="peity"
|
|
:height="svgHeight"
|
|
:width="svgWidth"
|
|
/>
|
|
</template>
|