本篇主要介绍自定义形状 Shape 的实现。 g2 5.0 当前 register 函数注册形状, register(`shape.${对应的mask}.${自定义形状名称}`, customShape 自定义形状函数) 注:customShape 需要在 chart 之后写,因为 customShape 回调入参中没有 chart 或 canvas 。
一、柱形图
/**
* 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 的不同。
二、柱形图(圆柱)
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;
}
}
每一个简单圆柱形是由两个平面图形组成。
一个椭圆的顶,四段 C 弧线(计算得当也可以为 两段)组成, 一个弧线 由 三个点组成。 一个不规则形状的体,四个 C 弧线 和 一段 L , Z 回连 组成。