效果圖如下:
html:
<canvas id="myCanvas" width="500" height="500"></canvas>
js:
toCanvas(arr) { let canvas = document.getElementById('myCanvas');//獲取canvas let ctx = canvas.getContext('2d');//通過getContext獲取畫圖的環境 let cont = 0; //總數 let start = 0; //起始弧度 let x = 250, y = 250; //圓點坐標 let startCoordinate = { start: 200, end: 100 }; //繪制起點坐標 arr.forEach((item) => { cont += item.number; }); //獲取number之和 arr.forEach((item) => { ctx.beginPath(); //初始化路徑 let prop = item.number / cont; //計算比例 let radian = prop * (Math.PI * 2); //計算弧度 ctx.arc(x, y, 100, start, start + radian, false);//根據比例和弧度畫圓 ctx.lineTo(x, y); //連接圓心畫線 ctx.fillStyle = item.color; //設置圓弧顏色 ctx.fill(); //填充樣式 let x1 = x + Math.cos(radian / 2 + start) * 100;//獲取圓弧中間點X坐標 let y1 = y + Math.sin(radian / 2 + start) * 100;//獲取圓弧中間點y坐標 ctx.moveTo(x1, y1);//畫筆移動到圓弧中點 ctx.lineTo(x1 + 30 * Math.cos(radian / 2 + start), y1 + 30 * Math.sin(radian / 2 + start));//在圓弧中點和圓心的連線上畫30單位長度的線 let proNumber = null; if (Math.cos(radian / 2 + start) > 0) { proNumber = 1 } else { proNumber = -1 }//判斷起點半徑與當前圓弧線所成角的余弦值是為負數/正數 ctx.lineTo(x1 + 30 * Math.cos(radian / 2 + start) + proNumber * 30, y1 + 30 * Math.sin(radian / 2 + start));//在之前線的基礎上畫一條30單位長度的水平線 ctx.fillText(item.name, x1 + 30 * Math.cos(radian / 2 + start) + proNumber * 20, y1 + 30 * Math.sin(radian / 2 + start) - 5, 30);//在線上填充字體,設置字體的坐標,最大長度 ctx.strokeStyle = item.color;//設置線條和字體的顏色 ctx.font = "bold 10px consolas";//設置字體的樣式 start += radian;//每次圓弧渲染完成將弧度累加作為下個圓弧的初始弧度 ctx.stroke();//渲染線條 }) let small = new Path2D(ctx);//創建新的一個路徑 small.arc(x, y, 60, 0, Math.PI * 2, false);//畫圓 ctx.fillStyle = "#fff";//設置圓的顏色 ctx.fill(small);//填充small },
let arrs = [{ name: '1號', color: '#CD853F', number: 500 }, { name: '2號', color: '#FFA500', number: 500 }, { name: '3號', color: '#FF4500', number: 200 }, { name: '4號', color: '#8B0000', number: 300 }, { name: '5號', color: '#DAA520', number: 50 }, ] this.toCanvas(arrs);
有些不滿意的是文字沒有和底下的線條保持一致的margin,也找了很多方法依然沒有成功。有大神看到了麻煩指點一下。萬分感謝。