Custom overlays
A chart renders its default slot inside its SVG. To draw your own marks, write a small component that reads the chart through a composable, and put it in the chart's default slot. The composables only work inside a chart, so call them in the child component, not in the component that renders the chart.
Plot area
usePlotArea() returns the box inside the axes as { x, y, width, height } in pixels.
<script setup>
import { usePlotArea } from 'vccs'
const plotArea = usePlotArea()
</script>
<template>
<g>
<line
:x1="plotArea.x"
:x2="plotArea.x + plotArea.width"
:y1="plotArea.y"
:y2="plotArea.y"
stroke="#14b8a6"
stroke-dasharray="4 4"
/>
<text
:x="plotArea.x + 4"
:y="plotArea.y - 6"
fill="#14b8a6"
font-size="12"
>
Plot area top
</text>
</g>
</template>
Data values to pixels
useXAxisScale() and useYAxisScale() return functions that map a data value to a pixel
position. Pass an axis id when the chart has more than one axis on that side.
<script setup>
import { computed } from 'vue'
import { useXAxisScale, useYAxisScale } from 'vccs'
const props = defineProps({
x: { type: String, required: true },
y: { type: Number, required: true },
label: { type: String, required: true },
})
const xScale = useXAxisScale()
const yScale = useYAxisScale()
const point = computed(() => {
const cx = xScale.value?.(props.x)
const cy = yScale.value?.(props.y)
return cx == null || cy == null ? undefined : { cx, cy }
})
</script>
<template>
<g v-if="point">
<circle
:cx="point.cx"
:cy="point.cy"
r="6"
fill="none"
stroke="#14b8a6"
stroke-width="2"
/>
<text
:x="point.cx"
:y="point.cy - 12"
fill="#14b8a6"
font-size="12"
text-anchor="middle"
>
{{ label }}
</text>
</g>
</template>
For a line, area or dot at a data value, the built-in reference elements are often enough.
Composables
Composables lists every composable, what it returns and in which charts it works.
Customized (deprecated)
Customized is deprecated and is removed in 2.0. It still works in 1.0 and warns once
in development. Move its slot content into a child component as shown above.
<!-- Before -->
<LineChart :data="data">
<Customized>
<template #default="{ offset }">
<line :x1="offset.left" :y1="offset.top" … />
</template>
</Customized>
</LineChart>
<!-- After: PlotAreaTop calls usePlotArea() -->
<LineChart :data="data">
<PlotAreaTop />
</LineChart>