chart

Forecast line chart with stripe pattern zone

Forecast line chart with stripe pattern zone

Загрузка превью…

src/chart/c-chart-17.vue

<!--
  Замена библиотеки: см. c-chart-13.vue / docs/PORTING.md §19/§27. Оригинал
  использует `ComposedChart` (`Area` без обводки + `Line` поверх — два
  разных recharts-примитива в одном холсте) — прямого аналога `ComposedChart`
  у vue-chrts нет. `AreaChart` неявно рисует и область, и линию для каждой
  категории одновременно (см. исходник `AreaChart.js`), что структурно
  близко: одна категория "forecast" даёт и заливку, и линию за раз.
  Диагональный SVG-паттерн заливки не переносится (та же причина, что у
  c-chart-13.vue). `ChartLegend` в оригинале — всегда видимая (не по hover)
  часть кадра, поэтому легенда воспроизведена через перенесённый
  `ChartLegendContent` с вручную собранным `payload` (тот же приём, что в
  кейсе `ui-chart`), а встроенная легенда `vue-chrts` скрыта.
-->
<script setup lang="ts">
import { AreaChart, CurveType } from "vue-chrts"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { ChartContainer, ChartLegendContent, type ChartConfig } from "@/components/ui/chart"

const chartData = [
  { month: "January", forecast: 2600 },
  { month: "February", forecast: 4200 },
  { month: "March", forecast: 2400 },
  { month: "April", forecast: 5000 },
  { month: "May", forecast: 2800 },
  { month: "June", forecast: 5800 },
  { month: "July", forecast: 3200 },
  { month: "August", forecast: 6200 },
  { month: "September", forecast: 3800 },
]

const chartConfig = {
  forecast: { label: "Forecast", color: "var(--chart-4)" },
} satisfies ChartConfig

const categories = { forecast: { name: "Forecast", color: "var(--chart-4)" } }

const legendPayload = [{ dataKey: "forecast", value: "forecast", color: "var(--chart-4)" }]

function xFormatter(tick: number) {
  return chartData[tick]?.month.slice(0, 3) ?? ""
}
</script>

<template>
  <Card class="w-full max-w-md">
    <CardHeader>
      <CardTitle>Sales Forecast</CardTitle>
      <CardDescription>Projected sales performance with trends</CardDescription>
    </CardHeader>
    <CardContent>
      <!--
        `recharts`' `ChartLegend`/`.recharts-legend-wrapper` is `position:
        absolute` inside the SAME fixed-height chart box (verified via
        getComputedStyle on the upstream render) — it overlays the plot area
        rather than adding to layout height. `vue-chrts` has no equivalent
        composable legend slot, so `ChartLegendContent` is placed here as an
        absolutely-positioned sibling inside the same `ChartContainer`
        (which already provides the chart context it needs via `useChart`)
        instead of a second, normal-flow `ChartContainer`, to match that
        same "overlay, don't grow the box" behavior instead of adding extra
        page height.
      -->
      <ChartContainer :config="chartConfig" class="relative">
        <AreaChart
          :data="chartData"
          :categories="categories"
          :height="200"
          :x-formatter="xFormatter"
          :curve-type="CurveType.Natural"
          :line-width="2.5"
          :duration="0"
          hide-tooltip
          hide-legend
        />
        <ChartLegendContent :payload="legendPayload" class="absolute inset-x-0 bottom-0 pt-0" />
      </ChartContainer>
    </CardContent>
  </Card>
</template>

Установка

npx shadcn-vue@latest add https://revueui.rootapi.dev/r/c-chart-17.json

Зависимости реестра

npm-зависимости

  • vue-chrts

Источник: порт из ReUI (Keenthemes, MIT)