数值格式

autoFormat

  • autoFormat 自动格式化, 优先级低于format若配置了 format 则以format为准
const Demo = () => {
  const vseed: VSeed = {
    chartType: 'column',
    dataset: [
      {
        profit: 12342.34567,
        sales: 23453.4567,
      },
    ],
    measures: [
      { id: 'profit', autoFormat: true },
      { id: 'sales', autoFormat: true },
    ],
  }

  if (zVSeed.safeParse(vseed).success) {
    console.log('zVSeed parse success!!!')
  } else {
    console.error('zVSeed parse error!!!')
  }

  return <SimpleVSeedRender vseed={vseed} />
}

import { useRef, useEffect, useState } from 'react'
import { useDark } from '@rspress/core/runtime'
import VChart, { ISpec } from '@visactor/vchart'
import {
  ListTable,
  ListTableConstructorOptions,
  PivotChart,
  PivotChartConstructorOptions,
  register,
} from '@visactor/vtable'
import { registerAll, VSeed, Builder, isPivotChart, isVChart, isVTable, zVSeed, Locale } from '@visactor/vseed'

registerAll()
register.chartModule('vchart', VChart)

const SimpleVSeedRender = (props: { vseed: VSeed }) => {
  const { vseed } = props
  const ref = useRef<HTMLDivElement>(null)
  const builderRef = useRef<Builder>(Builder.from({ chartType: 'line', dataset: [] }))
  const dark = useDark()
  const [locale, setLocale] = useState<Locale>('en-US')

  useEffect(() => {
    if (!ref.current) {
      return
    }
    const theme = dark ? 'dark' : 'light'
    const builder = Builder.from({ ...vseed, theme, locale })
    const spec = builder.build()

    builderRef.current = builder
    if (isPivotChart(vseed)) {
      const tableInstance = new PivotChart(ref.current, spec as PivotChartConstructorOptions)
      return () => tableInstance.release()
    } else if (isVChart(vseed)) {
      const vchart = new VChart(spec as ISpec, { dom: ref.current })
      vchart.renderSync()
      return () => vchart.release()
    } else if (isVTable(vseed)) {
      const tableInstance = new ListTable(ref.current, spec as ListTableConstructorOptions)
      return () => tableInstance.release()
    }
  }, [vseed, dark, locale])

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column' }}
      onClick={() => {
        console.group(`selected ${vseed.chartType}`)
        console.log('builder', builderRef.current)
        console.log('spec', builderRef.current?.spec)
        console.log('vseed', builderRef.current?.vseed)
        console.log('advancedVSeed', builderRef.current?.advancedVSeed)
        console.groupEnd()
      }}
    >
      <div>
        {['en-US', 'zh-CN'].map((d) => {
          return (
            <span key={d} style={{ margin: '0 2px' }}>
              <button
                onClick={() => setLocale(d)}
                style={{ fontSize: 10, padding: '0 2px', border: '1px solid #cccccc' }}
              >
                {d}
              </button>
            </span>
          )
        })}
      </div>
      <div ref={ref} style={{ height: 300, width: '100%' }}></div>
    </div>
  )
}

export default Demo

format

  • format 数值格式化配置, 优先级高于autoFormat

type

  • number 数值 (十进制)
  • percent 百分比 (0.00%)
  • permille 千分比 (0.00‰)
  • scientific 科学计数法 (1.23e+3)
const Demo = () => {
  const vseed: VSeed = {
    chartType: 'column',
    dataset: [
      {
        profit: 1234.4567,
        sales: 1234.4567,
        count: 1234.4567,
      },
    ],
    measures: [
      { id: 'profit', format: { type: 'percent' } },
      { id: 'sales', format: { type: 'permille' } },
      { id: 'count', format: { type: 'scientific' } },
    ],
  }

  if (zVSeed.safeParse(vseed).success) {
    console.log('zVSeed parse success!!!')
  } else {
    console.error('zVSeed parse error!!!')
  }

  return <SimpleVSeedRender vseed={vseed} />
}

import { useRef, useEffect, useState } from 'react'
import { useDark } from '@rspress/core/runtime'
import VChart, { ISpec } from '@visactor/vchart'
import {
  ListTable,
  ListTableConstructorOptions,
  PivotChart,
  PivotChartConstructorOptions,
  register,
} from '@visactor/vtable'
import { registerAll, VSeed, Builder, isPivotChart, isVChart, isVTable, zVSeed, Locale } from '@visactor/vseed'

registerAll()
register.chartModule('vchart', VChart)

const SimpleVSeedRender = (props: { vseed: VSeed }) => {
  const { vseed } = props
  const ref = useRef<HTMLDivElement>(null)
  const builderRef = useRef<Builder>(Builder.from({ chartType: 'line', dataset: [] }))
  const dark = useDark()

  useEffect(() => {
    if (!ref.current) {
      return
    }
    const theme = dark ? 'dark' : 'light'
    const builder = Builder.from({ ...vseed, theme })
    const spec = builder.build()

    builderRef.current = builder
    if (isPivotChart(vseed)) {
      const tableInstance = new PivotChart(ref.current, spec as PivotChartConstructorOptions)
      return () => tableInstance.release()
    } else if (isVChart(vseed)) {
      const vchart = new VChart(spec as ISpec, { dom: ref.current })
      vchart.renderSync()
      return () => vchart.release()
    } else if (isVTable(vseed)) {
      const tableInstance = new ListTable(ref.current, spec as ListTableConstructorOptions)
      return () => tableInstance.release()
    }
  }, [vseed, dark])

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column' }}
      onClick={() => {
        console.group(`selected ${vseed.chartType}`)
        console.log('builder', builderRef.current)
        console.log('spec', builderRef.current?.spec)
        console.log('vseed', builderRef.current?.vseed)
        console.log('advancedVSeed', builderRef.current?.advancedVSeed)
        console.groupEnd()
      }}
    >
      <div ref={ref} style={{ height: 300, width: '100%' }}></div>
    </div>
  )
}

export default Demo

thousandSeparator

  • thousandSeparator 千分位分隔符
const Demo = () => {
  const vseed: VSeed = {
    chartType: 'column',
    dataset: [
      {
        profit: 12344567,
        sales: 12344567,
        count: 12344567,
      },
    ],
    measures: [
      { id: 'profit', format: { type: 'percent', thousandSeparator: true } },
      { id: 'sales', format: { type: 'permille', thousandSeparator: false } },
      { id: 'count', format: { type: 'number', thousandSeparator: true } },
    ],
  }

  if (zVSeed.safeParse(vseed).success) {
    console.log('zVSeed parse success!!!')
  } else {
    console.error('zVSeed parse error!!!')
  }

  return <SimpleVSeedRender vseed={vseed} />
}

import { useRef, useEffect, useState } from 'react'
import { useDark } from '@rspress/core/runtime'
import VChart, { ISpec } from '@visactor/vchart'
import {
  ListTable,
  ListTableConstructorOptions,
  PivotChart,
  PivotChartConstructorOptions,
  register,
} from '@visactor/vtable'
import { registerAll, VSeed, Builder, isPivotChart, isVChart, isVTable, zVSeed, Locale } from '@visactor/vseed'

registerAll()
register.chartModule('vchart', VChart)

const SimpleVSeedRender = (props: { vseed: VSeed }) => {
  const { vseed } = props
  const ref = useRef<HTMLDivElement>(null)
  const builderRef = useRef<Builder>(Builder.from({ chartType: 'line', dataset: [] }))
  const dark = useDark()

  useEffect(() => {
    if (!ref.current) {
      return
    }
    const theme = dark ? 'dark' : 'light'
    const builder = Builder.from({ ...vseed, theme })
    const spec = builder.build()

    builderRef.current = builder
    if (isPivotChart(vseed)) {
      const tableInstance = new PivotChart(ref.current, spec as PivotChartConstructorOptions)
      return () => tableInstance.release()
    } else if (isVChart(vseed)) {
      const vchart = new VChart(spec as ISpec, { dom: ref.current })
      vchart.renderSync()
      return () => vchart.release()
    } else if (isVTable(vseed)) {
      const tableInstance = new ListTable(ref.current, spec as ListTableConstructorOptions)
      return () => tableInstance.release()
    }
  }, [vseed, dark])

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column' }}
      onClick={() => {
        console.group(`selected ${vseed.chartType}`)
        console.log('builder', builderRef.current)
        console.log('spec', builderRef.current?.spec)
        console.log('vseed', builderRef.current?.vseed)
        console.log('advancedVSeed', builderRef.current?.advancedVSeed)
        console.groupEnd()
      }}
    >
      <div ref={ref} style={{ height: 300, width: '100%' }}></div>
    </div>
  )
}

export default Demo

ratio & symbol

  • ratio 比例
  • symbol 单位
const Demo = () => {
  const vseed: VSeed = {
    chartType: 'column',
    dataset: [
      {
        num1: 1,
        num2: 10,
        num3: 100,
        num4: 1000,
        num5: 10000,
        num6: 100000,
        num7: 1000000,
        num8: 10000000,
        num9: 100000000,
      },
    ],
    measures: [
      { id: 'num1', format: { type: 'number', fractionDigits: 0, ratio: 1, symbol: '' } },
      { id: 'num2', format: { type: 'number', fractionDigits: 0, ratio: 10, symbol: '十' } },
      { id: 'num3', format: { type: 'number', fractionDigits: 0, ratio: 100, symbol: '百' } },
      { id: 'num4', format: { type: 'number', fractionDigits: 0, ratio: 1000, symbol: '千' } },
      { id: 'num5', format: { type: 'number', fractionDigits: 0, ratio: 10000, symbol: '万' } },
      { id: 'num6', format: { type: 'number', fractionDigits: 0, ratio: 100000, symbol: '十万' } },
      { id: 'num7', format: { type: 'number', fractionDigits: 0, ratio: 1000000, symbol: '百万' } },
      { id: 'num8', format: { type: 'number', fractionDigits: 0, ratio: 10000000, symbol: '千万' } },
      { id: 'num9', format: { type: 'number', fractionDigits: 0, ratio: 100000000, symbol: '亿' } },
    ],
    yAxis: {
      log: true,
      logBase: 10,
    },
  }

  if (zVSeed.safeParse(vseed).success) {
    console.log('zVSeed parse success!!!')
  } else {
    console.error('zVSeed parse error!!!')
  }

  return <SimpleVSeedRender vseed={vseed} />
}

import { useRef, useEffect, useState } from 'react'
import { useDark } from '@rspress/core/runtime'
import VChart, { ISpec } from '@visactor/vchart'
import {
  ListTable,
  ListTableConstructorOptions,
  PivotChart,
  PivotChartConstructorOptions,
  register,
} from '@visactor/vtable'
import { registerAll, VSeed, Builder, isPivotChart, isVChart, isVTable, zVSeed, Locale } from '@visactor/vseed'

registerAll()
register.chartModule('vchart', VChart)

const SimpleVSeedRender = (props: { vseed: VSeed }) => {
  const { vseed } = props
  const ref = useRef<HTMLDivElement>(null)
  const builderRef = useRef<Builder>(Builder.from({ chartType: 'line', dataset: [] }))
  const dark = useDark()

  useEffect(() => {
    if (!ref.current) {
      return
    }
    const theme = dark ? 'dark' : 'light'
    const builder = Builder.from({ ...vseed, theme })
    const spec = builder.build()

    builderRef.current = builder
    if (isPivotChart(vseed)) {
      const tableInstance = new PivotChart(ref.current, spec as PivotChartConstructorOptions)
      return () => tableInstance.release()
    } else if (isVChart(vseed)) {
      const vchart = new VChart(spec as ISpec, { dom: ref.current })
      vchart.renderSync()
      return () => vchart.release()
    } else if (isVTable(vseed)) {
      const tableInstance = new ListTable(ref.current, spec as ListTableConstructorOptions)
      return () => tableInstance.release()
    }
  }, [vseed, dark])

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column' }}
      onClick={() => {
        console.group(`selected ${vseed.chartType}`)
        console.log('builder', builderRef.current)
        console.log('spec', builderRef.current?.spec)
        console.log('vseed', builderRef.current?.vseed)
        console.log('advancedVSeed', builderRef.current?.advancedVSeed)
        console.groupEnd()
      }}
    >
      <div ref={ref} style={{ height: 300, width: '100%' }}></div>
    </div>
  )
}

export default Demo

fractionDigits

  • fractionDigits 小数位, 必须大于等于0, 否则不生效.
const Demo = () => {
  const vseed: VSeed = {
    chartType: 'column',
    dataset: [
      {
        num0: 123.456,
        num1: 123.456,
        num2: 123.456,
        num3: 123.456,
        num4: 123.456,
        num5: 234.567,
        num6: 234.567,
        num7: 234.567,
        num8: 345.678,
        num9: 345.678,
        num9: 400,
      },
    ],
    measures: [
      { id: 'num0', format: { type: 'number', fractionDigits: 0 } },
      { id: 'num1', format: { type: 'number', fractionDigits: 1 } },
      { id: 'num2', format: { type: 'number', fractionDigits: 2 } },
      { id: 'num3', format: { type: 'number', fractionDigits: 3 } },
      { id: 'num4', format: { type: 'number', fractionDigits: 4 } },
      { id: 'num5', format: { type: 'number', fractionDigits: 5 } },
      { id: 'num6', format: { type: 'number', fractionDigits: 6 } },
      { id: 'num7', format: { type: 'number', fractionDigits: 7 } },
      { id: 'num8', format: { type: 'number', fractionDigits: 8 } },
      { id: 'num9', format: { type: 'number', fractionDigits: 9 } },
    ],
    yAxis: {},
  }

  if (zVSeed.safeParse(vseed).success) {
    console.log('zVSeed parse success!!!')
  } else {
    console.error('zVSeed parse error!!!')
  }

  return <SimpleVSeedRender vseed={vseed} />
}

import { useRef, useEffect, useState } from 'react'
import { useDark } from '@rspress/core/runtime'
import VChart, { ISpec } from '@visactor/vchart'
import {
  ListTable,
  ListTableConstructorOptions,
  PivotChart,
  PivotChartConstructorOptions,
  register,
} from '@visactor/vtable'
import { registerAll, VSeed, Builder, isPivotChart, isVChart, isVTable, zVSeed, Locale } from '@visactor/vseed'

registerAll()
register.chartModule('vchart', VChart)

const SimpleVSeedRender = (props: { vseed: VSeed }) => {
  const { vseed } = props
  const ref = useRef<HTMLDivElement>(null)
  const builderRef = useRef<Builder>(Builder.from({ chartType: 'line', dataset: [] }))
  const dark = useDark()

  useEffect(() => {
    if (!ref.current) {
      return
    }
    const theme = dark ? 'dark' : 'light'
    const builder = Builder.from({ ...vseed, theme })
    const spec = builder.build()

    builderRef.current = builder
    if (isPivotChart(vseed)) {
      const tableInstance = new PivotChart(ref.current, spec as PivotChartConstructorOptions)
      return () => tableInstance.release()
    } else if (isVChart(vseed)) {
      const vchart = new VChart(spec as ISpec, { dom: ref.current })
      vchart.renderSync()
      return () => vchart.release()
    } else if (isVTable(vseed)) {
      const tableInstance = new ListTable(ref.current, spec as ListTableConstructorOptions)
      return () => tableInstance.release()
    }
  }, [vseed, dark])

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column' }}
      onClick={() => {
        console.group(`selected ${vseed.chartType}`)
        console.log('builder', builderRef.current)
        console.log('spec', builderRef.current?.spec)
        console.log('vseed', builderRef.current?.vseed)
        console.log('advancedVSeed', builderRef.current?.advancedVSeed)
        console.groupEnd()
      }}
    >
      <div ref={ref} style={{ height: 300, width: '100%' }}></div>
    </div>
  )
}

export default Demo

significantDigits

  • significantDigits 有效数字, 必须大于0, 否则不生效
const Demo = () => {
  const vseed: VSeed = {
    chartType: 'column',
    dataset: [
      {
        num0: 123.456,
        num1: 123.456,
        num2: 123.456,
        num3: 123.456,
        num4: 123.456,
        num5: 234.567,
        num6: 234.567,
        num7: 234.567,
        num8: 345.678,
        num9: 345.678,
        num9: 1000,
      },
    ],
    measures: [
      { id: 'num0', format: { type: 'number', significantDigits: 0 } },
      { id: 'num1', format: { type: 'number', significantDigits: 1 } },
      { id: 'num2', format: { type: 'number', significantDigits: 2 } },
      { id: 'num3', format: { type: 'number', significantDigits: 3 } },
      { id: 'num4', format: { type: 'number', significantDigits: 4 } },
      { id: 'num5', format: { type: 'number', significantDigits: 5 } },
      { id: 'num6', format: { type: 'number', significantDigits: 6 } },
      { id: 'num7', format: { type: 'number', significantDigits: 7 } },
      { id: 'num8', format: { type: 'number', significantDigits: 8 } },
      { id: 'num9', format: { type: 'number', significantDigits: 9 } },
    ],
  }

  if (zVSeed.safeParse(vseed).success) {
    console.log('zVSeed parse success!!!')
  } else {
    console.error('zVSeed parse error!!!')
  }

  return <SimpleVSeedRender vseed={vseed} />
}

import { useRef, useEffect, useState } from 'react'
import { useDark } from '@rspress/core/runtime'
import VChart, { ISpec } from '@visactor/vchart'
import {
  ListTable,
  ListTableConstructorOptions,
  PivotChart,
  PivotChartConstructorOptions,
  register,
} from '@visactor/vtable'
import { registerAll, VSeed, Builder, isPivotChart, isVChart, isVTable, zVSeed, Locale } from '@visactor/vseed'

registerAll()
register.chartModule('vchart', VChart)

const SimpleVSeedRender = (props: { vseed: VSeed }) => {
  const { vseed } = props
  const ref = useRef<HTMLDivElement>(null)
  const builderRef = useRef<Builder>(Builder.from({ chartType: 'line', dataset: [] }))
  const dark = useDark()

  useEffect(() => {
    if (!ref.current) {
      return
    }
    const theme = dark ? 'dark' : 'light'
    const builder = Builder.from({ ...vseed, theme })
    const spec = builder.build()

    builderRef.current = builder
    if (isPivotChart(vseed)) {
      const tableInstance = new PivotChart(ref.current, spec as PivotChartConstructorOptions)
      return () => tableInstance.release()
    } else if (isVChart(vseed)) {
      const vchart = new VChart(spec as ISpec, { dom: ref.current })
      vchart.renderSync()
      return () => vchart.release()
    } else if (isVTable(vseed)) {
      const tableInstance = new ListTable(ref.current, spec as ListTableConstructorOptions)
      return () => tableInstance.release()
    }
  }, [vseed, dark])

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column' }}
      onClick={() => {
        console.group(`selected ${vseed.chartType}`)
        console.log('builder', builderRef.current)
        console.log('spec', builderRef.current?.spec)
        console.log('vseed', builderRef.current?.vseed)
        console.log('advancedVSeed', builderRef.current?.advancedVSeed)
        console.groupEnd()
      }}
    >
      <div ref={ref} style={{ height: 300, width: '100%' }}></div>
    </div>
  )
}

export default Demo

roundingPriority

若同时设置了 fractionDigitssignificantDigits,则 roundingPriority 会生效, 默认为 lessPrecision

  • lessPrecision 更少精度, 尽可能的以 significantDigits 为准, 但如果 significantDigits 不足, 则以 significantDigits 为准
  • morePrecision 更多精度, 尽可能的以 fractionDigits 为准, 但如果 fractionDigits 不足, 则以 significantDigits 为准
const Demo = () => {
  const vseed: VSeed = {
    chartType: 'column',
    dataset: [
      {
        num0: 123.456,
        num1: 123.456,
        num2: 123.456,
        num3: 123.456,
        num4: 123.456,
        num5: 234.567,
        num6: 234.567,
        num7: 234.567,
        num8: 345.678,
        num9: 345.678,
        num9: 1000,
      },
    ],
    measures: [
      {
        id: 'num0',
        format: { type: 'number', significantDigits: 0, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
      {
        id: 'num1',
        format: { type: 'number', significantDigits: 1, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
      {
        id: 'num2',
        format: { type: 'number', significantDigits: 2, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
      {
        id: 'num3',
        format: { type: 'number', significantDigits: 3, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
      {
        id: 'num4',
        format: { type: 'number', significantDigits: 4, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
      {
        id: 'num5',
        format: { type: 'number', significantDigits: 5, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
      {
        id: 'num6',
        format: { type: 'number', significantDigits: 6, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
      {
        id: 'num7',
        format: { type: 'number', significantDigits: 7, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
      {
        id: 'num8',
        format: { type: 'number', significantDigits: 8, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
      {
        id: 'num9',
        format: { type: 'number', significantDigits: 9, fractionDigits: 2, roundingPriority: 'morePrecision' },
      },
    ],
  }

  if (zVSeed.safeParse(vseed).success) {
    console.log('zVSeed parse success!!!')
  } else {
    console.error('zVSeed parse error!!!')
  }

  return <SimpleVSeedRender vseed={vseed} />
}

import { useRef, useEffect, useState } from 'react'
import { useDark } from '@rspress/core/runtime'
import VChart, { ISpec } from '@visactor/vchart'
import {
  ListTable,
  ListTableConstructorOptions,
  PivotChart,
  PivotChartConstructorOptions,
  register,
} from '@visactor/vtable'
import { registerAll, VSeed, Builder, isPivotChart, isVChart, isVTable, zVSeed, Locale } from '@visactor/vseed'

registerAll()
register.chartModule('vchart', VChart)

const SimpleVSeedRender = (props: { vseed: VSeed }) => {
  const { vseed } = props
  const ref = useRef<HTMLDivElement>(null)
  const builderRef = useRef<Builder>(Builder.from({ chartType: 'line', dataset: [] }))
  const dark = useDark()
  const [roundingPriority, setRoundingPriority] = useState('morePrecision')

  useEffect(() => {
    if (!ref.current) {
      return
    }
    const theme = dark ? 'dark' : 'light'
    vseed.measures?.forEach((d) => {
      d.format.roundingPriority = roundingPriority
    })

    const builder = Builder.from({ ...vseed, theme })
    const spec = builder.build()

    builderRef.current = builder
    if (isPivotChart(vseed)) {
      const tableInstance = new PivotChart(ref.current, spec as PivotChartConstructorOptions)
      return () => tableInstance.release()
    } else if (isVChart(vseed)) {
      const vchart = new VChart(spec as ISpec, { dom: ref.current })
      vchart.renderSync()
      return () => vchart.release()
    } else if (isVTable(vseed)) {
      const tableInstance = new ListTable(ref.current, spec as ListTableConstructorOptions)
      return () => tableInstance.release()
    }
  }, [vseed, dark, roundingPriority])

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column' }}
      onClick={() => {
        console.group(`selected ${vseed.chartType}`)
        console.log('builder', builderRef.current)
        console.log('spec', builderRef.current?.spec)
        console.log('vseed', builderRef.current?.vseed)
        console.log('advancedVSeed', builderRef.current?.advancedVSeed)
        console.groupEnd()
      }}
    >
      <div>
        {['lessPrecision', 'morePrecision'].map((d) => {
          return (
            <span key={d} style={{ margin: '0 2px' }}>
              <button
                onClick={() => setRoundingPriority(d)}
                style={{ fontSize: 10, padding: '0 2px', border: '1px solid #cccccc' }}
              >
                {d}
              </button>
            </span>
          )
        })}
      </div>
      <div ref={ref} style={{ height: 300, width: '100%' }}></div>
    </div>
  )
}

export default Demo

roundingMode

  • roundingMode 四舍五入模式, 默认为 halfExpand
  • floor
  • ceil
  • expand
  • trunc
  • halfCeil
  • halfFloor
  • halfExpand
  • halfTrunc
  • halfEven
const Demo = () => {
  const vseed: VSeed = {
    chartType: 'column',
    dataset: [
      {
        num0: 123.34,
        num1: 123.38,
        num2: -123.34,
        num3: -123.38,
        num4: 123.34,
        num5: 234.38,
        num6: -234.34,
        num7: -234.38,
        num8: 4.5,
        num9: 3.5,
      },
    ],
    measures: [
      { id: 'num0', format: { type: 'number', fractionDigits: 1, roundingMode: 'floor' } },
      { id: 'num1', format: { type: 'number', fractionDigits: 1, roundingMode: 'ceil' } },
      { id: 'num2', format: { type: 'number', fractionDigits: 1, roundingMode: 'expand' } },
      { id: 'num3', format: { type: 'number', fractionDigits: 1, roundingMode: 'trunc' } },
      { id: 'num4', format: { type: 'number', fractionDigits: 1, roundingMode: 'halfCeil' } },
      { id: 'num5', format: { type: 'number', fractionDigits: 1, roundingMode: 'halfFloor' } },
      { id: 'num6', format: { type: 'number', fractionDigits: 1, roundingMode: 'halfExpand' } },
      { id: 'num7', format: { type: 'number', fractionDigits: 1, roundingMode: 'halfTrunc' } },
      { id: 'num8', format: { type: 'number', fractionDigits: 0, roundingMode: 'halfEven' } },
      { id: 'num9', format: { type: 'number', fractionDigits: 0, roundingMode: 'halfEven' } },
    ],
  }

  if (zVSeed.safeParse(vseed).success) {
    console.log('zVSeed parse success!!!')
  } else {
    console.error('zVSeed parse error!!!')
  }

  return <SimpleVSeedRender vseed={vseed} />
}

import { useRef, useEffect, useState } from 'react'
import { useDark } from '@rspress/core/runtime'
import VChart, { ISpec } from '@visactor/vchart'
import {
  ListTable,
  ListTableConstructorOptions,
  PivotChart,
  PivotChartConstructorOptions,
  register,
} from '@visactor/vtable'
import { registerAll, VSeed, Builder, isPivotChart, isVChart, isVTable, zVSeed, Locale } from '@visactor/vseed'

registerAll()
register.chartModule('vchart', VChart)

const SimpleVSeedRender = (props: { vseed: VSeed }) => {
  const { vseed } = props
  const ref = useRef<HTMLDivElement>(null)
  const builderRef = useRef<Builder>(Builder.from({ chartType: 'line', dataset: [] }))
  const dark = useDark()

  useEffect(() => {
    if (!ref.current) {
      return
    }
    const theme = dark ? 'dark' : 'light'

    const builder = Builder.from({ ...vseed, theme })
    const spec = builder.build()

    builderRef.current = builder
    if (isPivotChart(vseed)) {
      const tableInstance = new PivotChart(ref.current, spec as PivotChartConstructorOptions)
      return () => tableInstance.release()
    } else if (isVChart(vseed)) {
      const vchart = new VChart(spec as ISpec, { dom: ref.current })
      vchart.renderSync()
      return () => vchart.release()
    } else if (isVTable(vseed)) {
      const tableInstance = new ListTable(ref.current, spec as ListTableConstructorOptions)
      return () => tableInstance.release()
    }
  }, [vseed, dark])

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column' }}
      onClick={() => {
        console.group(`selected ${vseed.chartType}`)
        console.log('builder', builderRef.current)
        console.log('spec', builderRef.current?.spec)
        console.log('vseed', builderRef.current?.vseed)
        console.log('advancedVSeed', builderRef.current?.advancedVSeed)
        console.groupEnd()
      }}
    >
      <div ref={ref} style={{ height: 300, width: '100%' }}></div>
    </div>
  )
}

export default Demo

suffix & prefix

  • suffix 后缀
  • prefix 前缀
const Demo = () => {
  const vseed: VSeed = {
    chartType: 'column',
    dataset: [
      {
        num0: 123.34,
        num1: 123.38,
        num2: -123.34,
        num3: -123.38,
        num4: 123.34,
        num5: 234.38,
        num6: -234.34,
        num7: -234.38,
        num8: 4.5,
        num9: 3.5,
      },
    ],
    measures: [
      { id: 'num0', format: { type: 'number', fractionDigits: 1, suffix: '¥' } },
      { id: 'num1', format: { type: 'number', fractionDigits: 1, suffix: '$' } },
      { id: 'num2', format: { type: 'number', fractionDigits: 1, suffix: '!' } },
      { id: 'num3', format: { type: 'number', fractionDigits: 1, suffix: '-' } },
      { id: 'num4', format: { type: 'number', fractionDigits: 1, suffix: '+' } },
      { id: 'num5', format: { type: 'number', fractionDigits: 1, prefix: '¥' } },
      { id: 'num6', format: { type: 'number', fractionDigits: 1, prefix: '$' } },
      { id: 'num7', format: { type: 'number', fractionDigits: 1, prefix: '!' } },
      { id: 'num8', format: { type: 'number', fractionDigits: 0, prefix: '-' } },
      { id: 'num9', format: { type: 'number', fractionDigits: 0, prefix: '+' } },
    ],
  }

  if (zVSeed.safeParse(vseed).success) {
    console.log('zVSeed parse success!!!')
  } else {
    console.error('zVSeed parse error!!!')
  }

  return <SimpleVSeedRender vseed={vseed} />
}

import { useRef, useEffect, useState } from 'react'
import { useDark } from '@rspress/core/runtime'
import VChart, { ISpec } from '@visactor/vchart'
import {
  ListTable,
  ListTableConstructorOptions,
  PivotChart,
  PivotChartConstructorOptions,
  register,
} from '@visactor/vtable'
import { registerAll, VSeed, Builder, isPivotChart, isVChart, isVTable, zVSeed, Locale } from '@visactor/vseed'

registerAll()
register.chartModule('vchart', VChart)

const SimpleVSeedRender = (props: { vseed: VSeed }) => {
  const { vseed } = props
  const ref = useRef<HTMLDivElement>(null)
  const builderRef = useRef<Builder>(Builder.from({ chartType: 'line', dataset: [] }))
  const dark = useDark()

  useEffect(() => {
    if (!ref.current) {
      return
    }
    const theme = dark ? 'dark' : 'light'

    const builder = Builder.from({ ...vseed, theme })
    const spec = builder.build()

    builderRef.current = builder
    if (isPivotChart(vseed)) {
      const tableInstance = new PivotChart(ref.current, spec as PivotChartConstructorOptions)
      return () => tableInstance.release()
    } else if (isVChart(vseed)) {
      const vchart = new VChart(spec as ISpec, { dom: ref.current })
      vchart.renderSync()
      return () => vchart.release()
    } else if (isVTable(vseed)) {
      const tableInstance = new ListTable(ref.current, spec as ListTableConstructorOptions)
      return () => tableInstance.release()
    }
  }, [vseed, dark])

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column' }}
      onClick={() => {
        console.group(`selected ${vseed.chartType}`)
        console.log('builder', builderRef.current)
        console.log('spec', builderRef.current?.spec)
        console.log('vseed', builderRef.current?.vseed)
        console.log('advancedVSeed', builderRef.current?.advancedVSeed)
        console.groupEnd()
      }}
    >
      <div ref={ref} style={{ height: 300, width: '100%' }}></div>
    </div>
  )
}

export default Demo