Canvas怎么实现环形饼图
发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,今天小编给大家分享一下Canvas怎么实现环形饼图的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来
千家信息网最后更新 2025年01月23日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安全错误
数据库的锁怎样保障安全
网络安全等保实施情况
软件开发自我夸奖
捷达网络技术有限公司
软件开发怎么评中级
杭州在行互联网科技有限公司
我国网络安全基本法是什么
亲子网络安全绘画
subscience免费数据库
安博通中国网络安全
数据库简称列名
scrapy怎么爬数据库
磁带机备份需要备份服务器吗
软件开发压力大可以做哪行
数据库表里的字段修改关键字
能检索外文图书的数据库有哪些
网络技术计算机三级难考吗
数据库不具备什么
国家网络安全宣传2020
在线数据库 免费
摩尔庄园b站服务器
java数据库索引建立
远程服务器安全管理办法
系统网络安全产品
数据库资源耗尽
联想服务器光盘怎么装系统
网络安全公益宣传你的信息你做主
拜登政府 网络安全
交通银行武汉软件开发中心
网络安全服务有哪几部分组成
梯度结构数据库表设计