Chart 数据图形

用于数据图形场景的 MoriUI 组件。

导入

import { ChartContainer, ChartLegendContent, ChartTooltipContent } from 'moriui'

示例

概览

柱状图展示数据。

柱状图 - 分组
近六个月桌面端与移动端访问量对比
<script setup lang="ts">
  import type { ChartConfig } from 'moriui'

  import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue'
  import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
    ChartContainer,
    ChartCrosshair,
    ChartTooltipContent,
    componentToString

  } from 'moriui'

  const months = ['一月', '二月', '三月', '四月', '五月', '六月']

  const chartData = [
    { month: '一月', desktop: 186, mobile: 80 },
    { month: '二月', desktop: 305, mobile: 200 },
    { month: '三月', desktop: 237, mobile: 120 },
    { month: '四月', desktop: 73, mobile: 190 },
    { month: '五月', desktop: 209, mobile: 130 },
    { month: '六月', desktop: 214, mobile: 140 }
  ]

  const chartConfig = {
    desktop: {
      label: '桌面端',
      color: '#2563eb'
    },
    mobile: {
      label: '移动端',
      color: '#60a5fa'
    }
  } satisfies ChartConfig

  const tooltipTemplate = componentToString(chartConfig, ChartTooltipContent, {
    labelFormatter: (_x: number) => chartData[_x]?.month ?? ''
  })
</script>

<template>
  <Card class="w-full">
    <CardHeader>
      <CardTitle>柱状图 - 分组</CardTitle>
      <CardDescription>近六个月桌面端与移动端访问量对比</CardDescription>
    </CardHeader>
    <CardContent>
      <ChartContainer :config="chartConfig" class="aspect-auto h-[250px] w-full">
        <VisXYContainer :data="chartData">
          <VisGroupedBar
            :x="(_d: unknown, i: number) => i"
            :y="[(d: { desktop: number }) => d.desktop, (d: { mobile: number }) => d.mobile]"
            :color="(_d: unknown, i: number) => `var(--color-${i === 0 ? 'desktop' : 'mobile'})`"
            :rounded-corners="4"
          />
          <VisAxis
            type="x"
            :tick-format="(tick: number) => months[tick] ?? ''"
            :grid-line="false"
            :tick-line="false"
          />
          <VisAxis type="y" :grid-line="false" :tick-line="false" />
          <ChartCrosshair :template="tooltipTemplate" />
        </VisXYContainer>
      </ChartContainer>
    </CardContent>
  </Card>
</template>

提示框

图表数据点提示。

<script setup lang="ts">
  import type { ChartConfig } from 'moriui'

  import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue'
  import { ChartContainer, ChartCrosshair, ChartTooltipContent, componentToString } from 'moriui'

  const months = ['一月', '二月', '三月', '四月', '五月', '六月']

  const chartData = [
    { month: '一月', desktop: 186, mobile: 80 },
    { month: '二月', desktop: 305, mobile: 200 },
    { month: '三月', desktop: 237, mobile: 120 },
    { month: '四月', desktop: 73, mobile: 190 },
    { month: '五月', desktop: 209, mobile: 130 },
    { month: '六月', desktop: 214, mobile: 140 }
  ]

  const chartConfig = {
    desktop: {
      label: '桌面端',
      color: '#2563eb'
    },
    mobile: {
      label: '移动端',
      color: '#60a5fa'
    }
  } satisfies ChartConfig

  const tooltipTemplate = componentToString(chartConfig, ChartTooltipContent, {
    indicator: 'dashed',
    labelFormatter: (_x: number) => chartData[_x]?.month ?? ''
  })
</script>

<template>
  <ChartContainer :config="chartConfig" class="min-h-[200px] w-full">
    <VisXYContainer :data="chartData">
      <VisGroupedBar
        :x="(_d: unknown, i: number) => i"
        :y="[(d: { desktop: number }) => d.desktop, (d: { mobile: number }) => d.mobile]"
        :color="(_d: unknown, i: number) => `var(--color-${i === 0 ? 'desktop' : 'mobile'})`"
        :rounded-corners="4"
      />
      <VisAxis
        type="x"
        :tick-format="(tick: number) => months[tick] ?? ''"
        :grid-line="false"
        :tick-line="false"
      />
      <VisAxis type="y" :grid-line="false" :tick-line="false" />
      <ChartCrosshair :template="tooltipTemplate" />
    </VisXYContainer>
  </ChartContainer>
</template>

图例

图表系列图例。

桌面端
移动端
<script setup lang="ts">
  import type { ChartConfig } from 'moriui'

  import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue'
  import { ChartContainer, ChartCrosshair, ChartLegendContent, ChartTooltipContent, componentToString } from 'moriui'

  const months = ['一月', '二月', '三月', '四月', '五月', '六月']

  const chartData = [
    { month: '一月', desktop: 186, mobile: 80 },
    { month: '二月', desktop: 305, mobile: 200 },
    { month: '三月', desktop: 237, mobile: 120 },
    { month: '四月', desktop: 73, mobile: 190 },
    { month: '五月', desktop: 209, mobile: 130 },
    { month: '六月', desktop: 214, mobile: 140 }
  ]

  const chartConfig = {
    desktop: {
      label: '桌面端',
      color: '#2563eb'
    },
    mobile: {
      label: '移动端',
      color: '#60a5fa'
    }
  } satisfies ChartConfig

  const tooltipTemplate = componentToString(chartConfig, ChartTooltipContent, {
    labelFormatter: (_x: number) => chartData[_x]?.month ?? ''
  })
</script>

<template>
  <ChartContainer :config="chartConfig" class="min-h-[200px] w-full">
    <VisXYContainer :data="chartData">
      <VisGroupedBar
        :x="(_d: unknown, i: number) => i"
        :y="[(d: { desktop: number }) => d.desktop, (d: { mobile: number }) => d.mobile]"
        :color="(_d: unknown, i: number) => `var(--color-${i === 0 ? 'desktop' : 'mobile'})`"
        :rounded-corners="4"
      />
      <VisAxis
        type="x"
        :tick-format="(tick: number) => months[tick] ?? ''"
        :grid-line="false"
        :tick-line="false"
      />
      <VisAxis type="y" :grid-line="false" :tick-line="false" />
      <ChartCrosshair :template="tooltipTemplate" />
    </VisXYContainer>
    <ChartLegendContent class="mt-4" />
  </ChartContainer>
</template>

RTL

从右到左的图表布局。

سطح المكتب
الجوال
<script setup lang="ts">
  import type { ChartConfig } from 'moriui'

  import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue'
  import {
    ChartContainer,
    ChartCrosshair,
    ChartLegendContent,
    ChartTooltipContent,
    DirectionProvider,
    componentToString
  } from 'moriui'

  const months = ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو']

  const chartData = [
    { month: 'يناير', desktop: 186, mobile: 80 },
    { month: 'فبراير', desktop: 305, mobile: 200 },
    { month: 'مارس', desktop: 237, mobile: 120 },
    { month: 'أبريل', desktop: 73, mobile: 190 },
    { month: 'مايو', desktop: 209, mobile: 130 },
    { month: 'يونيو', desktop: 214, mobile: 140 }
  ]

  const chartConfig = {
    desktop: {
      label: 'سطح المكتب',
      color: '#2563eb'
    },
    mobile: {
      label: 'الجوال',
      color: '#60a5fa'
    }
  } satisfies ChartConfig

  const tooltipTemplate = componentToString(chartConfig, ChartTooltipContent, {
    labelFormatter: (_x: number) => chartData[_x]?.month ?? ''
  })
</script>

<template>
  <DirectionProvider direction="rtl">
    <ChartContainer :config="chartConfig" class="min-h-[200px] w-full" dir="rtl">
      <VisXYContainer :data="chartData">
        <VisGroupedBar
          :x="(_d: unknown, i: number) => i"
          :y="[(d: { desktop: number }) => d.desktop, (d: { mobile: number }) => d.mobile]"
          :color="(_d: unknown, i: number) => `var(--color-${i === 0 ? 'desktop' : 'mobile'})`"
          :rounded-corners="4"
        />
        <VisAxis
          type="x"
          :tick-format="(tick: number) => months[tick] ?? ''"
          :grid-line="false"
          :tick-line="false"
        />
        <VisAxis type="y" :grid-line="false" :tick-line="false" />
        <ChartCrosshair :template="tooltipTemplate" />
      </VisXYContainer>
      <ChartLegendContent class="mt-4" />
    </ChartContainer>
  </DirectionProvider>
</template>

使用说明

组合方式

Chart 基于 Unovis 构建,使用 ChartContainer 包裹 Vis 图表组件,通过 ChartTooltipContent 和 ChartLegendContent 提供交互辅助。

RTL

图表坐标轴在 RTL 页面中自动翻转。

变体

Chart 没有视觉变体;使用不同 Vis 组件(VisBar、VisLine、VisArea 等)表达数据。

可访问性

ChartContainer 生成的 SVG 图表应提供可访问的标题和描述。tooltip 应确保键盘用户可达。

API 参考

属性类型默认值说明
ChartContainer configChartConfig图表配置,定义系列名称、颜色和标签。
ChartContainer classHTMLAttributes["class"]undefined合并到图表容器的调用方类。
ChartTooltipContent indicatorChartTooltipIndicator'dot'提示框中的指示器类型。
ChartLegendContent classHTMLAttributes["class"]undefined合并到图例的调用方类。