使用原生 Canvas API 自定义 Pattern
/**
* A recreation of this demo: https://g2plot.antv.antgroup.com/examples/plugin/pattern/#heatmap-cookie-pattern
*/
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
width: 550,
height: 500,
paddingBottom: 80,
});
function applyStyle(ctx, style) {
return Object.entries(style).forEach(([k, v]) => (ctx[k] = v));
}
function createCanvas(w, h) {
const canvas = document.createElement('canvas');
const dpr = window.devicePixelRatio;
canvas.width = w * dpr;
canvas.height = h * dpr;
canvas.style.width = `${w}px`;
canvas.style.height = `${h}px`;
canvas.getContext('2d').scale(dpr, dpr);
return canvas;
}
function drawRect(ctx, w, h, fill) {
applyStyle(ctx, { fillStyle: fill });
ctx.fillRect(0, 0, w, h);
}
function drawLinePattern(ctx, color, width, height, cross = false) {
applyStyle(ctx, { globalAlpha: 1, strokeStyle: color, strokeOpacity: 0.9 });
applyStyle(ctx, { lineWidth: 0.5, lineCap: 'square' });
const d = `
M 0 ${-height} L ${width * 2} ${height}
M ${-width} ${-height} L ${width} ${height}
M ${-width} 0 L ${width} ${height * 2}`;
ctx.stroke(new Path2D(d));
if (cross) {
const d1 = `
M ${-width} ${height} L ${width} ${-height}
M ${-width} ${height * 2} L ${width * 2} ${-height}
M 0 ${height * 2} L ${width * 2} 0`;
ctx.stroke(new Path2D(d1));
}
}
// create pattern with raw Canvas API
const createPattern = (color, stroke, cross = false, density = false) => {
const spacing = density ? 3 : 5;
const width = Math.abs(spacing / Math.sin(Math.PI / 4));
const height = spacing / Math.sin(Math.PI / 4);
const canvas = createCanvas(width, height);
const ctx = canvas.getContext('2d');
drawRect(ctx, width, height, color);
drawLinePattern(ctx, stroke, width, height, cross);
return canvas;
};
const pattern1 = createPattern('#edaa53', '#44120c', true, true);
const pattern2 = createPattern('#edaa53', '#44120c', true);
const pattern3 = createPattern('#edaa53', '#fff');
chart.options({
type: 'cell',
data: {
type: 'fetch',
value:
'https://gw.alipayobjects.com/os/bmw-prod/68d3f380-089e-4683-ab9e-4493200198f9.json',
},
encode: { x: 'name', y: 'country', color: '#edaa53' },
style: {
radius: Infinity,
inset: 1,
shadowBlur: 10,
shadowColor: 'rgba(0,0,0,0.3)',
fill: ({ value }) => {
return {
image:
60 <= value && value < 90
? pattern1
: value >= 50
? pattern2
: pattern3,
repetition: 'repeat',
};
},
},
animate: { enter: { type: 'fadeIn' } },
});
chart.render();