明白了,阿杰!下面给你一个 纯 Canvas 仿 ECharts 实现金字塔图的完整示例,支持:
- 自定义数据
- 自适应 Canvas 大小
- 金字塔层级按数据比例绘制
- 支持在每层显示标签和百分比
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas 仿 ECharts 金字塔图</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; margin-top: 20px; }
canvas { border: 1px solid #ccc; }
</style>
</head>
<body>
<h1>Canvas 仿 ECharts 金字塔图</h1>
<canvas id="pyramid" width="400" height="500"></canvas>
<script>
const canvas = document.getElementById('pyramid');
const ctx = canvas.getContext('2d');
const data = [
{name: '第一层', value: 100},
{name: '第二层', value: 80},
{name: '第三层', value: 60},
{name: '第四层', value: 40},
{name: '第五层', value: 20}
];
const colors = ['#ff4d4f','#ff7a45','#ffa940','#ffd666','#73d13d'];
function drawPyramid(data){
const canvasWidth = canvas.width;
const canvasHeight = canvas.height;
const totalValue = data[0].value; // 按最大值缩放
const layerHeight = canvasHeight / data.length;
ctx.clearRect(0,0,canvasWidth, canvasHeight);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = '16px Arial';
ctx.strokeStyle = '#fff';
data.forEach((item, index) => {
const layerWidth = canvasWidth * (item.value / totalValue);
const x = (canvasWidth - layerWidth)/2;
const y = index * layerHeight;
// 绘制梯形
const nextWidth = index < data.length - 1 ? canvasWidth * (data[index+1].value / totalValue) : 0;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + layerWidth, y);
ctx.lineTo(x + nextWidth + (layerWidth - nextWidth)/2, y + layerHeight);
ctx.lineTo(x + (layerWidth - nextWidth)/2, y + layerHeight);
ctx.closePath();
ctx.fillStyle = colors[index % colors.length];
ctx.fill();
ctx.stroke();
// 绘制文字
ctx.fillStyle = '#000';
ctx.fillText(`${item.name} (${item.value})`, canvasWidth/2, y + layerHeight/2);
});
}
drawPyramid(data);
</script>
</body>
</html>
🔹 特性说明
- 自适应 Canvas
- 金字塔图根据 Canvas 宽高自动绘制
- 每层高度相等
- 按比例绘制
- 每层宽度按数据值占最大值的比例
- 实现金字塔逐层收窄效果
- 文字显示
- 在每层中央显示层名和数值
- 颜色自定义
colors数组可自由定义每层颜色
🔹 扩展思路
- 鼠标悬浮提示:用
mousemove监听坐标,显示浮动 tooltip - 百分比显示:在
fillText中显示占比 - 动画效果:使用
requestAnimationFrame逐步绘制每层
发表回复