怎么用 G2 自定义一个 2.5D 柱形图

avatar
数据可视化 @蚂蚁集团

感谢 cssdemeili 投稿。

背景

公司内部使用 G2 做数据可视化大屏,由于公司需要准备一些立体的图表,就调研了一下自定义的 shape,就大体做了一下立体的柱状图,看起来还不错,希望有更好的体验!

这个案列就是一个柱子是由 3 个多边形组合形成的:

  1. 左侧,右侧,上面都是独立的一个四边形
  2. 每个四边形的点的坐标不同,来绘制出组合的立体柱状图

实现

自定义 Shape

首先需要自定义一个 G2 5.0 的 shape。

function customGraph() {
  return (points: any, size: any) => {
    const x3 = points[1][0] - points[0][0]
    const x4 = x3 / 2 + points[0][0]
    const { document } = chart.context().canvas!
    const g = document.createElement('g', {})

    const r = document.createElement('polygon', {
      style: {
        points: [
          [points[0][0], points[0][1]],
          [x4, points[1][1] + 8],
          [x4, points[3][1] + 8],
          [points[3][0], points[3][1]]
        ],
        fill: 'rgba(114, 177, 207, 0.5)',
        stroke: 'rgba(0,0,0,0.1)',
        strokeOpacity: 0.1,
        inset: 30
      }
    })

    const p = document.createElement('polygon', {
      style: {
        points: [
          [x4, points[1][1] + 8],
          [points[1][0], points[1][1]],
          [points[2][0], points[2][1]],
          [x4, points[2][1] + 8]
        ],
        fill: 'rgba(126, 212, 236, 0.5)',
        stroke: 'rgba(0,0,0,0.3)',
        strokeOpacity: 0.1
      }
    })

    const t = document.createElement('polygon', {
      style: {
        points: [
          [points[0][0], points[0][1]],
          [x4, points[1][1] - 8],
          [points[1][0], points[1][1]],
          [x4, points[1][1] + 8]
        ],
        fill: 'rgba(173, 240, 255, 0.65)'
      }
    })

    g.appendChild(r)
    g.appendChild(p)
    g.appendChild(t)

    return g
  }
}

这里主要使用 G 的 API 去创建一个单独的柱子,然后这个回调函数中有对应这个柱子的位置信息。

注册到 G2 中

import { register } from '@antv/g2';

register('shape.interval.solidBarDiagram', customGraph);

绘制图形使用自定义图形

import { Chart, register } from '@antv/g2'

 const datalist = [
  { year: '1951 年', sales: 38 },
  { year: '1952 年', sales: 52 },
  { year: '1956 年', sales: 61 },
  { year: '1957 年', sales: 145 },
  { year: '1958 年', sales: 48 },
  { year: '1959 年', sales: 38 },
  { year: '1960 年', sales: 38 },
  { year: '1962 年', sales: 38 },
  { year: '1963 年', sales: 65 },
  { year: '1964 年', sales: 122 },
  { year: '1967 年', sales: 132 },
  { year: '1968 年', sales: 144 }
];

//调用这个函数就行
function drawPowercharts(dom: HTMLDivElement, datalist: any) {
  const chart = new Chart({
    container: dom,
    autoFit: true
  })

  chart
    .interval()
    .data(datalist)
    .encode('x', 'year')
    .encode('y', 'sales')
    .style('shape', 'solidBarDiagram')
    .scale('x', { padding: 0.3 })

  chart.line().data(datalist).encode('x', 'year').encode('y', 'sales').style({
    stroke: 'rgb(136, 240, 255)',
    lineWidth: 2
  })

  chart.point().data(datalist).encode('x', 'year').encode('y', 'sales').style({
    stroke: 'rgb(141, 150, 160,0.5)',
    lineWidth: 2,
    fill: 'rgb(136, 240, 255)'
  })

  chart.legend('year', {
    width: 10
  })

  chart.interaction({
    type: 'tooltip'
  })

  chart.render()
}

大功告成。效果如下图,也可以放到 G2 官网的 demo 框预览。

总结

总之自定义 shape 是用 canvas 的一下 api,对 canvas 有所了解的应该用起来比较顺手!