g2 5.0 柱形图2.5D 简单实现

363 阅读2分钟

本篇主要介绍自定义形状 Shape 的实现。 g2 5.0 当前 register 函数注册形状, register(`shape.${对应的mask}.${自定义形状名称}`, customShape 自定义形状函数) 注:customShape 需要在 chart 之后写,因为 customShape 回调入参中没有 chart 或 canvas 。

一、柱形图

image.png

/**
 * A recreation of this demo: https://observablehq.com/@d3/bar-chart
 */
import { Chart, register } from '@antv/g2';

register('shape.interval.customShape', customShape);

const chart = new Chart({
  container: 'container',
  theme: 'classic',
  autoFit: true,
});

chart
  .interval()
  .data({
    type: 'fetch',
    value:
      'https://gw.alipayobjects.com/os/bmw-prod/fb9db6b7-23a5-4c23-bbef-c54a55fee580.csv',
  })
  .encode('x', 'letter')
  .encode('y', 'frequency')
  .encode('shape', 'customShape')
  .axis('y', { labelFormatter: '.0%' });

chart.render();

function customShape() {
  return (points) => {
    const { document } = chart.getContext().canvas;
    const g = document.createElement('g', {});

      const centerX = (points[0][0] + points[1][0]) / 2;
          const w =  points[1][0] - points[0][0];

    const t1 = document.createElement('polygon', {
      style: {
        points: [
          points[0],
          [centerX, points[0][1] + w / 3],
          [centerX, points[2][1] + w / 3],
          points[3],
        ],
        fill: 'rgba(0, 0, 255, 0.85)'
      }
    });

    const t2 = document.createElement('polygon', {
      style: {
        points: [
          [centerX, points[0][1] + w / 3],
          points[1],
          points[2],
          [centerX, points[2][1] + w / 3],
        ],
        fill: 'rgba(0, 0, 255, 0.55)'
      }
    });

    const r = document.createElement('path', {
      style: {
        path: [
          ['M', ...points[0]],
          ['L', centerX, points[0][1] - w / 3],
          ['L', ...points[1]],
          ['L', centerX, points[0][1] + w / 3],
          ['Z']
        ],
        fill: 'rgba(0, 0, 255, 0.25)'
      }
    });

    g.appendChild(t1);
    g.appendChild(t2);
    g.appendChild(r);

    return g;
  }
}

每一个柱形都是由三个平面形状组成。 规则的多边形可以由 document.createElement('polygon') 或者 document.createElement('path') 创建。区别为 points 和 path 的不同。

image.png

image.png

二、柱形图(圆柱)

image.png

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

register('shape.interval.customShape', customShape);

const chart = new Chart({
  container: 'container',
  theme: 'classic',
  autoFit: true,
});

chart
  .interval()
  .data({
    type: 'fetch',
    value:
      'https://gw.alipayobjects.com/os/bmw-prod/fb9db6b7-23a5-4c23-bbef-c54a55fee580.csv',
  })
  .encode('x', 'letter')
  .encode('y', 'frequency')
  .encode('shape', 'customShape')
  .axis('y', { labelFormatter: '.0%' });

chart.render();

function customShape() {
  return (points) => {
    const { document } = chart.getContext().canvas;
    const g = document.createElement('g', {});

    const centerX = (points[0][0] + points[1][0]) / 2;
    const w = points[1][0] - points[0][0];

    const h1 = points[0][1] - w / 4;
    const h2 = points[0][1] + w / 4;

    const g1 = points[2][1] + w / 4;

    const t1 = document.createElement('path', {
      style: {
        path: [
          ['M', ...points[0]],
          ['C',
            ...points[0],
            points[0][0],
            h2,
            centerX,
            h2,
          ],
          ['C',
            centerX,
            h2,
            points[1][0],
            h2,
            ...points[1],
          ],
          ['L', ...points[2]],
          ['C',
            ...points[2],
            points[2][0],
            g1,
            centerX,
            g1,
          ],
          ['C',
            centerX,
            g1,
            points[0][0],
            g1,
            ...points[3],
          ],
          ['Z']
        ],
        fill: 'rgba(255, 0, 0, 0.75)'
      }
    });

    const r = document.createElement('path', {
      style: {
        path: [
          ['M', ...points[0]],
          ['C',
            ...points[0],
            points[0][0],
            h1,
            centerX,
            h1,
          ],
          ['C',
            centerX,
            h1,
            points[1][0],
            h1,
            ...points[1],
          ],
          ['C',
            ...points[1],
            points[1][0],
            h2,
            centerX,
            h2
          ],
          ['C',
            centerX,
            h2,
            points[0][0],
            h2,
            ...points[0],
          ],
          ['Z']
        ],
        fill: 'rgba(255, 0, 0, 0.4)'
      }
    });

    g.appendChild(t1);
    g.appendChild(r);

    return g;
  }
}

每一个简单圆柱形是由两个平面图形组成。

image.png

一个椭圆的顶,四段 C 弧线(计算得当也可以为 两段)组成, 一个弧线 由 三个点组成。 一个不规则形状的体,四个 C 弧线 和 一段 L , Z 回连 组成。