本文给大家带来了在canvas上绘制饼图的方法(代码)的介绍。 有一定的参考价值。 有需要的同学可以参考一下。 希望对您有所帮助。
1. 任务说明
使用原生画布 API 绘制饼图(南丁格尔玫瑰)。 (截图和数据来自百度Echarts官方示例库【查看示例链接】)。
2. 重要提示
绘制南丁格尔玫瑰图的方法有很多种。 Echarts 提供两种不同的模式:直径或面积。 本文以面积比例绘制法为例。 绘图算法如下:
确定每个轨道的角度。 因为所有轨迹的角度加起来为 2π,所以我们首先根据数据比来估计角度:
每一位轨迹的面积与总面积的比值就是值的比值。 给定参数字段options.radius中的最大值和最小值作为具有最大值的扇区的绘图数据。 代入以下公式即可得到总面积S:
然后利用上面的公式估算出每个扇形对应的外圆直径,在画布中绘制路径并填充。
3. 示例代码
南丁格尔玫瑰图绘制示例代码:
//绘制饼图 drawPieChart(options); /** * 绘制饼图 * @param {[type]} options [description] * @return {[type]} [description] */ function drawPieChart(options) { //记录最大数值以反求面积总和 options.maxValue = 0; //求数据集总和以在后续计算每个扇形的角度比例 options.totalNum = options.data.reduce((pre,cur)=>{ if (cur.value > options.maxValue) { options.maxValue = cur.value; } return pre+cur.value; },0); /*以最大值对应最大半径来计算面积总和,并覆盖原值 *使得最大的一块扇形外圆半径为options.radius[0] *内圆半径为options.radius[1] */ let Rmin = options.radius[0]; let Rmax = options.radius[1]; let r = Math.sqrt((Rmax*Rmax - Rmin*Rmin)*options.totalNum / options.maxValue + Rmin*Rmin); options.radius[1] = r; //移动坐标系原点至绘图中心 let paintingCenter={ x:parseInt(options.center[0],10)/100 * (options.chartZone[2] - options.chartZone[0]) + options.chartZone[0], y:parseInt(options.center[1],10)/100 * (options.chartZone[3] - options.chartZone[1]) + options.chartZone[1] } context.translate(paintingCenter.x, paintingCenter.y); //绘制每个扇形,过程中累加旋转角度 let allAngle = options.data.reduce((prev,cur,index)=>{ context.fillStyle = options.colorPool[index] let angle = calcPaintingData(cur,options); return prev + angle; },0); //绘制中空白色圆 context.beginPath(); context.fillStyle = 'white'; context.arc(0,0,options.radius[0],0,2*Math.PI,false); context.fill(); } /** * 计算每个扇形所需要的绘图参数 */ function calcPaintingData(data,options) { let scale = data.value / options.totalNum; let angle = scale * 2 * Math.PI; let Rmin = options.radius[0]; let Rmax = options.radius[1]; let r = Math.sqrt(scale * (Rmax*Rmax - Rmin*Rmin) + Rmin*Rmin); data.r = r; //绘制扇形 paintFan({ r:r, angle:angle, data:data, options:options }); return angle;//将角度值返回给外层函数以供累加 } //绘制扇形 function paintFan(opt) { context.beginPath(); context.lineTo(opt.r,0); context.arc(0,0,opt.r,0,opt.angle,false); context.lineTo(0,0); context.closePath(); context.fill(); context.rotate(opt.angle); }
登录后复制
疗效可以在浏览器中查看:
四。 Hover突出显示实现思路
在绘图过程中,每个轨迹的绘图数据(直径、相对于圆心的起始角、轨迹角度)都安装在绘图数据上。 监听canvas标签上的键盘通讯波mousemovecss饼图,并在bounce函数上将键盘通讯波event.clientX和event.clientY转换为相对于canvas坐标(mouseX,mouseY)的值。 从圆心坐标(paintingCenter.x,paintingCenter.y)到(mouseX,mouseY)的连接是一个向量。 根据向量的角度和模数css饼图,可以判断键盘是否在某个轨道上。 如果进展顺利,请使用过渡动画对悬停效果设置关键帧。 首先将context.fillStyle颜色更改为轨道对应的高条纹,然后以线性方式逐帧将外圆绘制直径减小到目标尺寸(例如10%)。 在每个帧中,使用画布绘图上下文重新封闭绘图区域。 线,然后填充它。
当悬停效果出现时,用高条纹勾勒出绘图区域的轮廓。 待悬停效果消失后,从外圈开始逐帧勾画红色内轨,最后将数据轨勾画为原来的颜色。