chart
Donut chart with center total
Donut chart with center total
Загрузка превью…
src/chart/c-chart-19.vue
<!--
Замена библиотеки: см. docs/PORTING.md §19/§27. Тело графика — `DonutChart`
из `vue-chrts` вместо recharts `Pie`. Иное API: `data` — плоский массив
чисел (не объекты), сегменты сопоставляются `categories` по индексу.
3D drop-shadow фильтр и per-segment линейные градиенты не переносятся —
`DonutChart` красит сегмент одним цветом из `categories`, без `url(#...)`.
Центральная надпись (сумма/подпись) воспроизведена через default-слот
`DonutChart`, который абсолютно позиционируется поверх графика — тот же
приём, что и в оригинале (`Label content` внутри `Pie`).
-->
<script setup lang="ts">
import { DonutChart } from "vue-chrts"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { ChartContainer, type ChartConfig } from "@/components/ui/chart"
const chartData = [
{ source: "direct", visits: 4200 },
{ source: "search", visits: 3600 },
{ source: "social", visits: 2800 },
{ source: "email", visits: 1900 },
{ source: "referral", visits: 1400 },
]
const total = chartData.reduce((s, d) => s + d.visits, 0)
const chartConfig = {
visits: { label: "Visits" },
direct: { label: "Direct", color: "var(--chart-1)" },
search: { label: "Search", color: "var(--chart-2)" },
social: { label: "Social", color: "var(--chart-3)" },
email: { label: "Email", color: "var(--chart-4)" },
referral: { label: "Referral", color: "var(--chart-5)" },
} satisfies ChartConfig
const categories = {
direct: { name: "Direct", color: "var(--chart-1)" },
search: { name: "Search", color: "var(--chart-2)" },
social: { name: "Social", color: "var(--chart-3)" },
email: { name: "Email", color: "var(--chart-4)" },
referral: { name: "Referral", color: "var(--chart-5)" },
}
const donutData = chartData.map((d) => d.visits)
</script>
<template>
<Card class="w-full max-w-xs">
<CardHeader class="items-center pb-0">
<CardTitle>Traffic Sources</CardTitle>
<CardDescription>Where your visitors come from</CardDescription>
</CardHeader>
<CardContent class="flex-1 pb-0">
<ChartContainer :config="chartConfig" class="mx-auto aspect-square max-h-[280px]">
<DonutChart
:data="donutData"
:categories="categories"
:radius="95"
:arc-width="30"
:pad-angle="0.02"
:height="280"
:duration="0"
hide-tooltip
hide-legend
>
<div class="flex flex-col items-center">
<span class="fill-foreground text-3xl font-bold tabular-nums">{{ (total / 1000).toFixed(1) }}k</span>
<span class="fill-muted-foreground text-xs">Total Visits</span>
</div>
</DonutChart>
</ChartContainer>
</CardContent>
</Card>
</template>