uni-app 之canvas绘制饼状图

一开始,对于canvas我是拒绝的,后来,我发现我爱上了它,像爱上小哥哥一样~~

  说起canvas,是css3新增的标签。而饼状图又是canvas经典,我们公司现在正在用uni-app框架去研发APP,平常我们使用canvas标签时,只需在HTML中增加一个canvas标签,然后再script中获取标签属性,var canvas = document.getElementById('cavsElem') 就可以了!但是,咱们也说了,使用uni-app,有过了解的人也知道,咱们uni-app是不支持document和window对象的,所以呢uni-app官网给我们提供了一个API --uni.createCanvasContext,他会创建一个画布,你要定义他的宽高,给这个画布一个id,然后你就可以随心多欲了~~~

我们想要的图是这样的:

  

我之前在调研这个canvas的时候,发现大家都做了那个就是解释说明,我就在延展的地方给大家写出来了,emmmmm,假如我有这么多钱,买了这么多化妆品~~

这个canvas把,我结合一下我当初调研的时候的感觉,就感觉还是给大家直接上代码比较好,解说什么的当时我都看不懂,我就一步一步的跟大家解释一下,让大家拿下他!!!像拿下心仪的小哥哥一样!!!加油,我们是最棒的!!(什么鬼~)

我们是在vue项目中写的 , 首先我先在一个vue组件中使用了canvas标签:

  定义canvas的大小宽高,给canvas定义一个id,在获取的时候能用到,我给了一个class样式,就是想让他居中的  ,,可忽略

<canvas style="width: 350px; height: 300px;" canvas-id="homeownerCanvas" class="homeowner-canvas_charts"></canvas>

  其次我在js中定义了所需要展示的数据,类型,所占比例的:

          let data = [{"money": 30 + '万',"value": 0.3,"color": "#afb4db","title": "口红"},{"money": 20 + '万',"value": 0.2,"color": "#ffce7b","title": "眼影"},{"money": 30 + '万',"value": 0.3,"color": "#f8aba6","title": "粉底"},{"money": 20 + '万',"value": 0.2,"color": "#afdfe4","title": "眉笔"}];

  这个东西我就不详细解释了 ,他这个的意思就是说定义要显示的数据,比如你看到的金钱,颜色(我看别人家的颜色有的是生成的,我就直接定义了颜色,毕竟咱们主题不是他),比值(比值这个问题就是说你自己当前的这个金钱在你所有的金钱中所占的比例,说白了就是1/10 = 0.1的事情),还有他的title?   就是他这个块是什么东西啦~~·

  然后就是在vue组件中引用关于canvas的js文件,现在vue组件中调用 :

     字段说明~参数一: canvasID    参数二:定义好的data     参数三:总数(自己可以计算啦~我直接写死了)这个是便于以后有别的组件也会使用canvas这个js文件,所以把会使用到的数据当做参数传送过去

  canvas.canvasGraph('homeownerCanvas',data,100)

  接下来就是重头戏 :canvas这个js文件了!!

// 图表封装
export default{canvasGraph(canvasID,data,summation){function PieChart(ctx,radius){//定义起始角度let tempAngle=0;//定圆心位置let x0=182,y0=150;       //伸出长度let outLine = 18;PieChart.prototype.init = function(data){this.drawPie(data);};    // 绘画扇形 及中心圆PieChart.prototype.drawPie = function(data){for (let i = 0; i < data.length; i++) {// 开始一个新路径
                    ctx.beginPath();// 移动到中心点
                    ctx.moveTo(x0,y0);//计算当前扇形角度   所占比例*360let angle = data[i].value*360;//当前扇形起始绘制弧度   360 = 2π  等于6.28let startAngle = tempAngle*Math.PI/180;//当前扇形借结束绘制弧度let endAngle = (tempAngle + angle)*Math.PI/180;//绘制扇形  x y中心  半径  开始弧度  结束弧度
                    ctx.arc(x0,y0,radius,startAngle,endAngle);//填充扇形ctx.fillStyle = data[i].color;// 填充
                    ctx.fill();// 调用添加标题解释方法this.drawTitle(startAngle,angle,data[i].color, data[i].title + data[i].money)//当前扇形结束绘制角度,即下一个扇形开始绘制角度tempAngle += angle;}// 开始一个新路径
                ctx.beginPath();// 开始画圆ctx.arc(x0, y0, 65, 0, 2 * Math.PI)// 填充颜色 白色ctx.setFillStyle('white')// 调用绘制中心圆文字方法this.drawCenterTitle()}// 伸出线条方法PieChart.prototype.drawTitle = function(startAngle,angle,color,title){// 伸出去的长度 斜边长度 等于半径加上定义好的长度  let out = radius;// 当前弧度的二分之一let du = startAngle+(angle/2)*Math.PI/180;// 计算伸出的点x坐标let outX = x0+out*Math.cos(du);// 计算伸出的点y坐标let outY = y0+out*Math.sin(du);// 开始一个新路径
                ctx.beginPath();// 移动到中心点
                ctx.moveTo(x0,y0);// 画出点到伸出点的一条线
                ctx.lineTo(outX,outY);// 线条颜色ctx.strokeStyle = color;//设置标题ctx.font = 'bold 14px Microsoft Yahei';// 计算出标题文字宽度let textWidth = ctx.measureText(title).width;// 计算标题样式ctx.textBaseline = "bottom";// 刷新配置项  象限判断 与 对应符号let optionArr=[{quadrant:outX>x0 && outY<y0,symbol:['+','-','left']},{quadrant:outX<x0 && outY<y0,symbol:['-','-','right']},{quadrant:outX<x0 && outY>y0,symbol:['-','+','right']},{quadrant:outX>x0 && outY>y0,symbol:['+','+','left']}]// 渲染的配置项let {symbol} = optionArr.find(el=>el.quadrant&&el.symbol)// 斜线起始点let slashState = eval(outX+symbol[0]+outLine)// 横线起始点let lineState = eval(outX+symbol[0]+textWidth+symbol[0]+outLine)// 终点let lineEnd = eval(outY+symbol[1]+outLine)// 标题文字样式ctx.textAlign = symbol[2];// 画出伸出的斜线
                ctx.lineTo(slashState,lineEnd);// 接上斜线画出标题下面的直线
                ctx.lineTo(lineState,lineEnd);// 填充标题
                ctx.fillText(title,slashState,lineEnd);// 填充
                ctx.stroke();}// 绘制中心文字PieChart.prototype.drawCenterTitle = function(){// 填充
                ctx.fill();// 文字大小ctx.setFontSize(24)// 文字颜色ctx.fillStyle = "#333333"// 文字位置ctx.setTextAlign('center')// 插入文字ctx.fillText(`${summation}万`, x0, y0+5)// 文字大小ctx.setFontSize(14)// 合计字体样式ctx.font = '14px Microsoft Yahei';// 文字颜色ctx.fillStyle = "#999999"// 插入文字ctx.fillText('合计(元)', x0, y0+30)// 开始画图
                ctx.draw()}}var ctx = uni.createCanvasContext(canvasID) var PieChart = new PieChart(ctx,90)PieChart.init(data)}}

详细解析:

  我使用了构造函数的原型添加方式

  //根据canvasID 获取当前传参的canvas信息  //定义起始角度(决定你是从哪里开始画)let tempAngle=0;//定圆心位置let x0=100,y0=150;  //定义伸出长度(指的是解释说明伸出的长度)let outLine = 18;  

  使用的原型的方法:

  PieChart.prototype.init = function(data){}     ------集合调用初始化函数创建对象后   参数为传参的dataPieChart.prototype.drawPie = function(data){}     ------画饼状图的扇形和画白色小圆的方法PieChart.prototype.drawTitle = function(startAngle,angle,color,title){}  -----画伸出的线条和文字PieChart.prototype.drawCenterTitle = function(){}   ---画白色圆上的文字

  来张图详细解析

 

这样的解释可还ok?   哈哈哈哈哈~~~~

接下来就是这个方法的分析

  主要呢就是这几个方法,不过呢,建议大家先去看一下这个canvas基本的方法什么的,要不然就会像我最开始接触的时候一团懵,不知道都是干啥的,大家可以先去了解一下方法都是什么意思,这样在捋的时候及不会乱了

   PieChart.prototype.drawPie = function(data){}   绘画扇形与白色圆

PieChart.prototype.drawPie = function(data){for (let i = 0; i < data.length; i++) {// 开始一个新路径ctx.beginPath();// 移动到中心点ctx.moveTo(x0,y0);//计算当前扇形角度   所占比例*360let angle = data[i].value*360;//当前扇形起始绘制弧度   360 = 2π  等于6.28let startAngle = tempAngle*Math.PI/180;//当前扇形借结束绘制弧度let endAngle = (tempAngle + angle)*Math.PI/180;//绘制扇形  x y中心  半径  开始弧度  结束弧度ctx.arc(x0,y0,radius,startAngle,endAngle);//填充扇形ctx.fillStyle = data[i].color;// 填充ctx.fill();// 调用添加标题解释方法this.drawTitle(startAngle,angle,data[i].color, data[i].title + data[i].money)//当前扇形结束绘制角度,即下一个扇形开始绘制角度tempAngle += angle;}// 开始一个新路径ctx.beginPath();// 开始画圆ctx.arc(x0, y0, 65, 0, 2 * Math.PI)// 填充颜色 白色ctx.setFillStyle('white')// 调用绘制中心圆文字方法this.drawCenterTitle()}

  这里的知识点就是咱们关于弧度与角度之间的换算  1弧度=180/π   1度=π/180      方法主要是写了 根据传入data中value所代表的百分比计算出各自所占有的角度,在通过换算计算出所占弧度,先计算出开始弧度,再计算结束弧度,画出扇形,然后遍历data,画出各自的扇形,一定切记,当你要画一个新的扇形或者别的形状的时候,一定要开启一个新路径,白色的小圆同样是这样,开启一个新路径然后用画圆的方法画个圆,另外在方法里面还调用了绘制标题的drawTitle()和绘制中心圆文字drawCenterTitle()方法

   PieChart.prototype.drawTitle = function(startAngle,angle,color,title){}     @param  {startAngle,angle,color,title}   开始弧度 当前角度 颜色 标题

  自我感觉这是个重点! 我当初在调研,在看别人写的时候入了一个不小的坑  ,后来仔细一算 发现他们写错了  我在这里给大家指正一下, 来张图片解释一下~~   要是有看不懂的,欢迎大家提出来,我会给大家解释的,嗯嗯嗯(若是看不清楚请见上面详细代码)

PieChart.prototype.drawCenterTitle = function(){} 绘制中心文字

PieChart.prototype.drawCenterTitle = function(){// 填充ctx.fill();// 文字大小ctx.setFontSize(24)// 文字颜色ctx.fillStyle = "#333333"// 文字位置ctx.setTextAlign('center')// 插入文字ctx.fillText(`${summation}万`, x0, y0+5)// 文字大小ctx.setFontSize(14)// 合计字体样式ctx.font = '14px Microsoft Yahei';// 文字颜色ctx.fillStyle = "#999999"// 插入文字ctx.fillText('合计(元)', x0, y0+30)// 开始画图ctx.draw()}

  具体方法就是这样了,如果你们有什么不会的或者还没有懂得,欢迎留言,或者你们想要什么效果的,都可以留言,大家一起交流,一起拿下“小哥哥”!!!

更正:由于当时的考虑不周的原因,发现当如果在你的data中有比例为零时,会不显示canvas图表,会报出一个'symbol is not defined' 的问题,后来寻找了一下错误点,发现了自己在象限的判断中考虑的并不周到,没有考虑到0的原因 ,故象限判断做出如下更改,其他不变:

// 象限判断
let optionArr=[{quadrant:outX>=x0 && outY<=y0,symbol:['+','-','left']},{quadrant:outX<x0 && outY<=y0,symbol:['-','-','right']},{quadrant:outX<x0 && outY>y0,symbol:['-','+','right']},{quadrant:outX>=x0 && outY>y0,symbol:['+','+','left']}
]

 注意:另外之前有人扣扣私聊我说他按照我这个代码写的,但是并没有显示图表,后来他把代码发给我,我发现他把canvas画图方法放在了onLoad上,后来给他放到onReady就显示了,在这里我讲一下为什么、

       onReady要比onLoad先执行,onLoad必须等到页面内包括图片的所有元素加载完毕之后才能执行,而onReady不需要,canvas说白了就是一张画布,所以在onLoad执行时不会显示的,因为当时的画布并没有加载完成

  

转载于:https://www.cnblogs.com/gongliying/p/11461508.html

uni-app 之canvas绘制饼状图相关推荐

  1. 第166天:canvas绘制饼状图动画

    canvas绘制饼状图动画 1.HTML 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 < ...

  2. 微信小程序之图表系列——canvas绘制饼状图,带点击效果

    一图胜千言,相信很多开发者都没有绕开过图表制作这个坑,在小程序中也是,当然可以用第三方echart等制图插件来做,但小程序要求代码量最大12M,还得分好几个包,一个echart插件就将近1M,要是只做 ...

  3. 570day(绘制饼状图1.html)

    <2019年4月28日>[连续 570天] 标题:绘制饼状图1.html: 内容: /*var myCanvas = document.querySelector('canvas');va ...

  4. 【Python 实战基础】如何绘制饼状图分析商品库存

    目录 一.实战场景 二.主要知识点 文件读写 基础语法 字符串处理 文件生成 数据构建 三.菜鸟实战 1.创建 python 文件 2.运行结果 一.实战场景 实战场景:如何绘制饼状图分析商品库存 二 ...

  5. 小程序 绘制饼状图

    写在前:按照比例绘制饼状图 实现效果: 布局 <view class="left"><cover-view class="white"> ...

  6. 【python图像处理】python绘制饼状图

    饼状图在统计分析中有着重要的应用,python中用于绘制饼状图是matplotlib中的pyplot类,这里就介绍一下,如何绘制饼状图. 直接看下面的代码 """ === ...

  7. QT绘制饼状图,自定义切片。

    QT绘制饼状图,自定义切片 项目简介 项目技术 项目展示 主要源码片段解析 获取完整项目源码传送门 项目简介 创建简单的甜甜圈图,以及对切片进行一些自定义. 项目技术 qt5.12,qt charts ...

  8. Python绘制饼状图对商品库存进行分析

    人生苦短,我用Python 一.序言 二.知识点 三.效果展示 四.代码展示 一.序言 今天来实践一下如何用Python对商品库存绘制饼状图进行分析 二.知识点 文件读写 基础语法 字符串处理 文件生 ...

  9. Python+Matplotlib绘制饼状图模拟南丁格尔玫瑰图

    开学第一课:一定不要这样问老师Python问题 董付国老师Python系列教材推荐与选用参考 ============= 版权声明:由于公众号后台规则问题,本文暂时无法设置原创标记,但仍属原创内容,微 ...

最新文章

  1. ASP.NET Web API 过滤器创建、执行过程(二)
  2. Less 常用基础知识
  3. 写一个函数DeleteRange删除单链表中结点的值在low 和high之间的结点
  4. Dubbo与SpringBoot整合流程(从实例入手,附代码下载)
  5. redis 持久化详解 RDB和AOF 优缺点
  6. CentOS系统恢复误删除的文件
  7. 系统架构师-基础到企业应用架构-服务层
  8. python面向对象类_python面向对象-类和对象
  9. Vue2.x总结(1)
  10. 读《DOOM启示录》随想
  11. C++17代码整洁之道
  12. 利用计算机辅助管理档案说明,计算机辅助档案管理
  13. 使用Android Studio 创建第一个Android 应用
  14. 写论文时引用作者名字
  15. JAVA测试人员考核_自动化测试的绩效考核
  16. java轮训算法_轮询算法 - 小虾米的java梦 - 博客园
  17. 云呐|固定资产管理的目的,固定资产管理办法的目的
  18. 安装好maya后运行不了并弹出如图的错误
  19. 一文读懂通信玩家半年财报,有人欢喜有人愁!
  20. 地震数据SEGY格式介绍及其查看分析(附示例地震数据)

热门文章

  1. Linux 单用户模式/救援模式更改root密码/关闭selinux
  2. 栈应用:括号匹配问题
  3. 荣耀30能用鸿蒙系统吗,华为荣耀30 Pro开始测试使用鸿蒙OS系统!
  4. 最实际与高效生成数据库高级声明式SQL脚本神器研发
  5. Tushare财经数据接口(三)案例——股票基本面统计
  6. Promise系列学习
  7. PHP中的MySQLi扩展学习(五)MySQLI_STMT对象操作
  8. 第6次面试:华某永道(2022-03-16)
  9. 目前流行的装修风格_2019最流行的装修风格,这些都很火!
  10. 如何使用Synopsys VCS在Vivado中编译库并执行仿真