Canvas怎么实现环形饼图
发表于:2024-11-25 作者:千家信息网编辑
千家信息网最后更新 2024年11月25日,今天小编给大家分享一下Canvas怎么实现环形饼图的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来
千家信息网最后更新 2024年11月25日Canvas怎么实现环形饼图
今天小编给大家分享一下Canvas怎么实现环形饼图的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
首先讲一下思路:
布局很简单,我就不写了,主要讲下作图过程。
首先跟图需求可以知道,作出这样的效果需要一组对象,每个对象有颜色,所占比例,名字等,也就是这样:
let chartData=[{color:"#FD7A4F",title:"其他",percent:0.2},{color:"#FDD764",title:"建筑/土木工程",percent:0.25},***]
注意百分比加在一起必须是100%,也就是1,否则圆环可能不会画满,或者多处一部分。
根据每部分所占比例计算出每个部分所占的弧度,使用ctx.arc(x0, y0,r, startAngle, endAngle);画出圆弧,当前项需要向外偏移一些,过程中具体上代码讲这部分:
首先定义一个multiCircleChart类,
//ES6写法class multiCircleChart { constructor(id, chartDatas, defalutIndex,callback) { /*构造函数: 传入的参数ID,canvas的id,用于放置绘画内容; chartDatas:画图所需参数数据; defalutIndex:defalutIndex:当前选中项 callback:点击环形图的回调函数 */ this.canvas = document.getElementById(id); this.size = this.canvas[xss_clean].clientWidth * 4; this.canvas.style.width = this.size / 4 + "px"; this.canvas.style.height = this.size / 4 + "px"; this.canvas.width = this.size; this.canvas.height = this.size; /* 因为在移动端画图需要多倍图,这样图像会很清晰,所以这里size,也就是canvas的context设置为canvas大小的4倍; 注意:!!!canvas.width指的是画布内容(context)的大小,cavas.style.width是canvas在页面上显示的大小,也就是说,真是的图片是显示图片大小的4倍 */ this.ctx = this.canvas.getContext("2d"); this.defalutIndex = defalutIndex;//当前选中项 this.chartDatas = chartDatas;//绘制所需数据 this.lineWidth = this.size/5;//环形图的圆环宽度,设置为canvas宽度的1/5; this.startAngle = -0.5;//环形图起始角度,这里为-0.5,计算时也就是-0.5*Math.PI,放在坐标系中也就是环形图最高点那个位置的角度;顺便说一下,右侧为0,下方为0.5,左侧为1 this.callback=callback; this.canvas.addEventListener('click',this.mouseDownEvent.bind(this)); /*给canvas添加监听函数,并将事件传递过去,用于计算点击位置在哪个数据项里*/ this.AngleList=[];//记录每一项的结束角度,结合监听事件,计算点击事件的位置在哪个数据项里 }}
构造函数写好了,接下来需要画环形图了:
class multiCircleChart { *** draw() { this.ctx.clearRect(0,0,this.size,this.size);//每次绘画前,先清空一下画布,避免画布被污染 if (this.chartDatas.length == 0) return;//如果传入的参数长度为0的话,也就不需要继续画了 this.ctx.lineWidth = this.lineWidth;//为圆环宽度赋值 let startAngle = Math.PI * -0.5;//设置起始角度 let endAngle = startAngle;设置结束角度 this.AngleList=[]; /*下面就开始动笔画图了*/ this.chartDatas.map((item, i) => { this.ctx.beginPath();//开始画图命令,避免粘连 this.ctx.strokeStyle = item.color;//设置边框颜色,因为我们画的是圆环,所以填充色不需要,只要有边框色就行了 if (i > 0) { //从第二项开始(i==1)时,起始角度就是上一次的结束角度 startAngle = endAngle; } endAngle = startAngle + item.percent * Math.PI * 2;//计算当前项的结束角度,根据所占的百分比计算所占角度(item.percent * Math.PI * 2),再结合起始角度就可以计算出真正的偏移角度了(startAngle + item.percent * Math.PI * 2) this.AngleList.push(endAngle); //选中当前项,需要向外偏移 if (i == this.defalutIndex) { /* 选中当前项,需要向外偏移 使用起始角度和结束角度的中间值来就算偏移位置 */ let centerAngle=(startAngle+endAngle)/2; let x=this.lineWidth*0.2*Math.cos(centerAngle);//x轴偏移量 let y=this.lineWidth*0.2*Math.sin(centerAngle);//y轴偏移量 //未选中项的圆心位置是(this.size / 2, this.size / 2),选中的需要偏移,圆心是(this.size / 2+x, this.size / 2+y);这样画出的环形就会向外偏移环形宽度的1/5了; this.ctx.arc(this.size / 2+x, this.size / 2+y, this.size / 2 - this.lineWidth / 2 - this.lineWidth * 0.2, startAngle, endAngle); } else { this.ctx.arc(this.size / 2, this.size / 2, this.size / 2 - this.lineWidth / 2 - this.lineWidth * 0.2, startAngle, endAngle); } this.ctx.stroke(); }); }}
现在所画的图是一个静态的,点击环形图是不会有任何变化的,当然现在这样也是可以用的:
let circlePeiChart = new multiCircleChart("circle-pei-chart",chartDatas,defalutIndex,);//new 一个 circlePeiChart.draw();//画图
外部切换选中项:
circlePeiChart.defalutIndex=2;//修改选中项Index值 circlePeiChart.draw();//重绘
那么怎样点击canvas切换当前选项呢,思路很简单:以canvas中心为圆心,监测点击位置,点击位置与圆心连成一线,以直角坐标系为参照,计算出点击位置的弧度,跟angleList做比较,计算出点击的是第几项,然后修改defalutIndex,重绘canvas.
class multiCircleChart { *** *** mouseDownEvent(e){ const [x1,y1]=[e.offsetX,e.offsetY];//点击事件位置 const [x0,y0]=[this.size/2/4,this.size/2/4];//原点位置;注意:原点位置为canvas中心,不是context中心 let angle=0; if(x1>x0){ //点击位置在第一象限(y1>y0)或者第二象限(y1y0) y1最后把整体代码贴上吧!
//html
//调用let chartDatas=[ {color: "rgb(253, 122, 79)",title: "后端开发",percent: 0.2}, **];let defalutIndex=0let circlePeiChart = new multiCircleChart("circle-pei-chart",chartDatas, defalutIndex,(i)=>{defalutIndex=i});circlePeiChart.draw();
//重绘circlePeiChart.defaultIndex=2;circlePeiChart.draw();
/*chartDatas [ {color: "rgb(253, 122, 79)",title: "后端开发",percent: 0.2}, **];*/class multiCircleChart { constructor(id, chartDatas, defalutIndex,callback) { this.canvas = document.getElementById(id); this.size = this.canvas[xss_clean].clientWidth * 4; this.canvas.style.width = this.size / 4 + "px"; this.canvas.style.height = this.size / 4 + "px"; this.canvas.width = this.size; this.canvas.height = this.size; this.ctx = this.canvas.getContext("2d"); this.defalutIndex = defalutIndex; this.chartDatas = chartDatas; this.lineWidth = this.size/5; this.startAngle = -0.5; this.callback=callback; this.canvas.addEventListener('click',this.mouseDownEvent.bind(this)); this.AngleList=[]; } draw() { this.ctx.clearRect(0,0,this.size,this.size); if (this.chartDatas.length == 0) return; this.ctx.lineWidth = this.lineWidth; this.ctx.lineCap="butt"; let startAngle = Math.PI * -0.5; let endAngle = startAngle; this.AngleList=[]; this.chartDatas.map((item, i) => { this.ctx.beginPath(); this.ctx.strokeStyle = item.color; if (i > 0) { startAngle = endAngle; } endAngle = startAngle + item.percent * Math.PI * 2; this.AngleList.push(endAngle); //选中当前项,需要向外偏移 if (i == this.defalutIndex) { //选中当前项,需要向外偏移 let centerAngle=(startAngle+endAngle)/2; let x=this.lineWidth*0.2*Math.cos(centerAngle); let y=this.lineWidth*0.2*Math.sin(centerAngle); this.ctx.arc(this.size / 2+x, this.size / 2+y, this.size / 2 - this.lineWidth / 2 - this.lineWidth * 0.2, startAngle, endAngle); } else { this.ctx.arc(this.size / 2, this.size / 2, this.size / 2 - this.lineWidth / 2 - this.lineWidth * 0.2, startAngle, endAngle); } this.ctx.stroke(); }); } mouseDownEvent(e){ const [x1,y1]=[e.offsetX,e.offsetY]; const [x0,y0]=[this.size/2/4,this.size/2/4]; let angle=0; if(x1>x0){ y1以上就是"Canvas怎么实现环形饼图"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。
位置
角度
偏移
环形
也就是
函数
前项
起始
事件
内容
圆心
圆环
大小
宽度
数据
知识
篇文章
参数
画布
象限
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
sql数据库备份 压缩
软件开发烧硬件
逍遥问道数据库修改教程
照片墙软件开发
北京游戏软件开发
扬杰科技服务器芯片
数据库商品编号的数据类型
报纸期刊数据库
讲师团队网络安全屏障
华阳国际软件开发盈利
苹果app服务器维护了吗
福州星空网络技术有限公司
nexis 数据库
禄杰网络技术有限
基础软件开发是什么
积极推进网络安全宣传周活动
七十数据库
大专计算机网络技术课
阴阳师转服务器可以消除鬼使黑吗
绝地求生2服务器不同能一起玩吗
明日之后服务器是啥时候开的
江苏前端软件开发怎么样
武术数据库
大数据时代网络安全法
车辆远程监控大数据库
传奇云服务器租用多少钱
如何提高网络安全整体性
网络工程师与软件开发工程师
天龙八部合区之后服务器登录
qq聊天服务器