d3-vx-helper

1.0.29 • Public • Published

d3-helper

d3 图形库,在vx上的二次封装

更多的是对于图形库复用的思考 核心:基础图形的复用及拼接

Why

  1. 使用 d3 以命令式的方式来进行图形的书写,不太便于图形的复用,往往需要通过函数抽象以及一大堆参数来重用
  2. 使用 d3 来进行图形的渲染已经非常方便,再抽象成 echart 那种根据配置进行渲染的方式没有太大必要,费时费力且效果差不多。
  3. vx 以单元拼接的方式来进行书写,非常满足我们的要求
  4. vx 默认样式并不符合我们的要求,重复的设置各种 props 时,跟我们使用 d3 的过程其实类似,依旧复杂
  5. 我们需要一种可变的复用单元。

API

其他请直接从@vx 中引用

  • Container
  • AxisLeft, AxisBottom, AxisTop, AxisRight
  • Grid, GridRows, GridColumns
  • Line, Bar, LinePath, AreaClosed
  • withTooltip, Tooltip
  • tickValues, withConfig
  • Group
  • scaleBand, scalePoint, scaleLinear, scaleTime, scaleLog, scalePower

使用方式

vx 非常巧妙的定义了各种图形单元,支持以声明式使用图形单元进行拼接, 我们对 vx 的默认样式进行了重置,并且添加了 Container 元素,用于定义图形容器

npm i d3-vx-helper
import { appleStock } from "@vx/mock-data";
import {
  Container,
  scaleLinear,
  scaleTime,
  Group,
  AxisLeft,
  AxisBottom,
  Grid,
  Bar,
  LinePath,
  AreaClosed
} from "d3-vx-helper";
 
// 定义getter
const x = d => new Date(d.date);
const y = d => +d.close;
 
// 定义容器配置
const padding = {
  top: 20,
  left: 40,
  bottom: 20,
  right: 20
};
 
export default class LineGraph {
  render() {
    return (
      <Container width={1000} height={200} padding={padding} x={x} y={y}>
        {({ width, height }) => {
          // 根据数据定义x,y轴的scale
          const xScale = scaleTime({
            rangeRound: [0, width],
            domain: d3.extent(data, x)
          });
          const yScale = scaleLinear({
            rangeRound: [height, 0],
            domain: d3.extent(data, y)
          });
 
          return (
            <Group>
              <Grid
                width={width}
                height={height}
                xScale={xScale}
                yScale={yScale}
              />
              <AxisBottom top={height} scale={xScale} />
              <AxisLeft scale={yScale} />
              <AreaClosed
                data={data}
                xScale={xScale}
                yScale={yScale}
                x={x}
                y={y}
              />
            </Group>
          );
        }}
      </Container>
    );
  }
}

withConfig

很多时候,我们更希望重用自定义单元,比如我的系统里有两种通用的折线样式,提供该方法进行封装, 我们可以在基础单元上不断的进行上层封装,以便灵活快速的使用。

import { LinePath, withConfig } from "d3-vx-helper";
 
export const DashedRedLine = withConfig({
  stroke: "red",
  strokeWidth: 1,
  strokeDasharray
})(LinePath);
 
export const BoldBlueLine = withConfig({
  stroke: "green",
  strokeWidth: 4
})(LinePath);

tooltip

在进行 tooltip 提示时,往往会比较吃力,我们也在配合 vx/shape 进行统新的封装, 提供两种 tooltip 类型,baseTooltip, lineTooltip

return (
  <Container
    padding={padding}
    x={x}
    y={y}
    // 定义tooltip格式
    tooltip={data => (
      <div>
        {String(x(data))}: {y(data)}
      </div>
    )}
  >
    {({ width, height, showBasicTooltip, showLineTooltip, hideTooltip }) => {
      const xScale = scaleTime({
        rangeRound: [0, width],
        domain: d3.extent(data, x)
      });
      const yScale = scaleLinear({
        rangeRound: [height, 0],
        domain: d3.extent(data, y)
      });
 
      return (
        <Group>
          <Grid width={width} height={height} xScale={xScale} yScale={yScale} />
          <AxisBottom top={height} scale={xScale} />
          <AxisLeft scale={yScale} />
          <Group className="line-graph">
            <AreaClosed
              data={data}
              xScale={xScale}
              yScale={yScale}
              x={x}
              y={y}
            />
            // 定义整个图形触发区间
            <Bar
              x={0}
              y={0}
              width={width}
              height={height}
              fill="transparent"
              data={data}
              onMouseMove={d => e =>
                showLineTooltip({
                  event: e,
                  data: d,
                  xScale,
                  yScale
                })}
              onMouseLeave={d => e => hideTooltip()}
            />
          </Group>
        </Group>
      );
    }}
  </Container>
);

withTooltip

对于复杂的 tooltip,或者多个 tooltip,可以用 withTooltip 装饰器来实现:

@withTooltip
class Area {
  render () {
    const {
      showTooltip,
      hideTooltip,
      tooltipData,
      tooltipTop,
      tooltipLeft
    } = this.props

    return <div>
      <Graph>
      <Tooltip ...>
    </div>
  }
}

tickValues

我们使用 axis.ticks 设置坐标的刻度是,往往产生的刻度数量是不准确的。 我们可以使用 axis.tickValues 使用指定的数组作为刻度。在这里我们提供一个方法,来自动获取精准数量的指定数组。

import { tickValues } from 'd3-vx-helper'
 
<AxisBottom tickValues={tickValues(4, [0, d3.max(data)])}>

Readme

Keywords

none

Package Sidebar

Install

npm i d3-vx-helper

Weekly Downloads

0

Version

1.0.29

License

ISC

Unpacked Size

1.26 MB

Total Files

61

Last publish

Collaborators

  • threatbook