3 个回答

https://codesandbox.io/s/twil...

首先是画饼图

var data = [150, 70];
var radius = 100;
var total = data.reduce((a, b) => a+b, 0);
var cx = 250; 
var cy = 250;
var startAngle = -Math.PI/2;
for (var i = 0; i < data.length; i++) {
   ctx.fillStyle = i > 0 ? 'skyblue' : 'hotpink';
   ctx.beginPath();
   ctx.moveTo(cx, cy);
   ctx.arc(cx, cy, radius, startAngle,startAngle + (Math.PI * 2 * (data[i] / total)), false);
   ctx.lineTo(cx, cy);
   ctx.fill();
   startAngle += Math.PI * 2 * (data[i] / total);
}

然后外边的弧线同样可以视为一个更大半径圆的一部分,定义一下这条线对应的角度,根据饼图数据,那么这个圆上的3个点的坐标都有了,代码不解释了,都是初中几何

const getPoint  = (angle, radius) => {
  angle -= Math.PI/2;
  var x = radius * Math.cos(angle);
  var y = radius * Math.sin(angle)
  return {x:x+cx, y:y+cy}
}

var totalAngle = Math.PI/2;
var percent = data[0]/total;
var r2 = radius+30;
var points = [
  getPoint(- totalAngle/2,r2),
  getPoint( totalAngle/2, r2),
  getPoint(-totalAngle/2 + totalAngle*percent, r2)
]

ctx.beginPath();
ctx.arc(cx, cy, r2,  -totalAngle/2-Math.PI/2, totalAngle/2-Math.PI/2, false);
ctx.stroke();

points.forEach(({x, y})=> {
  ctx.fillStyle = '#f60';
  ctx.beginPath(x, y);
  ctx.arc(x, y, 6, 0, Math.PI * 2, false);
  ctx.fill();
})
推荐问题
宣传栏