当前项目大量 Web 需求,目前需要将 native 的效果同步到 Web,一顿百度各种图表库,F2·移动端可视化引擎 | AntV (antgroup.com)
Apache ECharts
一顿百度,发现添加圆头很麻烦,也没找到如何解决,最后只能用 canvas 自己来绘制了
Tab-环形图 (online-video-cutter.com).gif
具体实现代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>环形图</title>
<style>
canvas {
border: 1px solid pink;
}
</style>
</head>
<body>
<canvas width="400" height="500"></canvas>
<script type="text/javascript">
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const size = Math.min(canvas.width, canvas.height)
// 解决 canvas 绘制毛边问题
const sizePX = `${size}px`
canvas.style.width = sizePX;
canvas.style.height = sizePX;
canvas.height = size * window.devicePixelRatio;
canvas.width = size * window.devicePixelRatio;
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
// 2秒动画
const duration = 2000;
let startTime = null;
const lineWidth = 20;
ctx.lineWidth = lineWidth;
// 设置线条末端为圆头效果
ctx.lineCap = 'round';
const data = [{
"value": 100,
"color": "red"
}, {
"value": 50,
"color": "blue"
}, {
"value": 15,
"color": "green"
}, {
"value": 20,
"color": "#ccc"
}];
const sum = 185;
//设置角度的中间变量
const x0 = size / 2;
const y0 = x0;
const radius = (size - lineWidth) / 2;
console.log(`size=${size} y0=${y0} radius=${radius} lineWidth=${lineWidth}`)
const mathPI = Math.PI / 180
function draw(progress) {
// 从-90度开始绘制
let tempAngle = -90;
const currAngle = 360 * progress
for (let i = 0; i < data.length; i++) {
//因为设置不同的颜色,所以每次绘制完起一个新状态
ctx.beginPath();
//当前扇形的角度
const angle = data[i].value / sum * currAngle;
ctx.strokeStyle = data[i].color;
//开始从 tempAngle 绘制
const startAngle = tempAngle * mathPI;
//从tempAngle 绘制到 我们自己的angle区域
const endAngle = (tempAngle + angle) * mathPI;
//x0,y0 圆心坐标,radius:半径,startAngle:开始绘制的弧度,endAngle:结束绘制的弧度
ctx.arc(x0, y0, radius, startAngle, endAngle);
ctx.stroke();
tempAngle += angle; //下一次绘制的起始角度
}
}
function animate(timestamp) {
if (!startTime) startTime = timestamp;
let progress = (timestamp - startTime) / duration;
if (progress > 1) progress = 1;
draw(progress);
if (progress < 1) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
</script>
</body>
</html>
网友评论