canvas 绘制圆弧
<!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>canvas-demo2</title> <style> * { margin: 0; padding: 0; } body { height: 100vh; overflow: hidden; } </style> </head> <body> <canvas id="canvas"></canvas> <script> let data = [ { plan: '计划一', zhanxian: 20, chengjiao: 30 }, { plan: '计划二', zhanxian: 30, chengjiao: 20 }, { plan: '计划三', zhanxian: 40, chengjiao: 10 }, { plan: '计划四', zhanxian: 50, chengjiao: 20 } ] const canvas = document.getElementById('canvas') canvas.width = document.body.clientWidth canvas.height = document.body.clientHeight const ctx = canvas.getContext('2d') ctx.translate(100, canvas.height - 500) // 处理数据 let plan = [] let zhanxian = [] let chengjiao = [] let x = 200; let y = 200; data.forEach((d, i) => { plan.push(d.plan) zhanxian.push(+d.zhanxian) chengjiao.push(+d.chengjiao) }) let datas = [zhanxian, chengjiao]
// datas循环 datas.forEach((arr, m) => { let s = 0 arr.forEach((d, i) => { s += d if (m == 1) { drawFan(arr, i, s, 500) } else { drawFan(arr, i, s) } }) }) function drawFan(arr, num, ss , cx) { // ctx.arc(x, y, 100, startAngle, endAngle, true) if (cx) x = cx ctx.beginPath() let s = sum(arr) let q = (arr[num] / s) let l = Math.PI / 180 * 1 // 起始角度 let sa = num == 0 ? 0 : (Math.PI * 2 * ((ss - arr[num]) / s)) // 结束角度 let ea = Math.PI * 2 * (ss) / s - l ctx.fillStyle = `rgb(${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)})` ctx.strokeStyle = `rgb(${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)})` ctx.arc(x, y, 100, sa, ea, false) ctx.lineTo(x,y) ctx.closePath() ctx.stroke() ctx.fill() } function sum (arr) { return arr.reduce((prev, cur) => prev + cur) } </script> </body> </html>
注意:data中的数据,比如'zhanxian'共4个数据,我们的目的是在所有数据画完后就应该是一个圆,所以每画完一个圆弧,它的结束角度就应该是下一个弧度的起始角度。这里是从“datas循环”中着手处理。