从一个渐变圆角进度条浅出画一个圆

开始

这一切需要从一个(简单)的需求开始,在最开始对设计第一眼看到这张图的时候,感觉挺简单的嘛,直接用echarts饼图模拟出来一个就好了

echarts

然后上echarts试了一下发现实现不出来了

设计图这边采用的是锥形渐变,而echarts只有线性渐变和径向渐变。

css

然后准备换种方案,css就有锥形渐变,然后通过conic-gradient加上mask画出了一个渐变的环形然后可以再通过剪裁实现出进度的展示。

但是存在两个问题,一个是conic-gradient属性兼容性不好ie和火狐都不支持,二个是后来发现了还存在一个需求进度条的两端需要有圆角,然后这种实现方式就不行了。

其实在写这篇文章的时候才想到一个方法就是在两端加上两个半圆形,不过得计算半圆形的位置。

Canvas & SVG

在我的理解中在页面上作图总共有四种方式。

  • dom+css
  • Canvas
  • SVG
  • WebGL

WebGL是一头雾水还是试试Canvas和SVG吧,因为更熟悉Canvas一些,我这边就采用Canvas来试试。

Canvas可以轻松的实现圆角和环形,但是他的api里面居然没有锥形渐变

然后就想着尝试手动来实现一个锥形渐变,然后查阅资料看到了一篇文章手把手教你画圆锥渐变,就是相当于画圆嘛,我们可以通过一条线一条线的画从而画出一个圆,然后把两端渐变的颜色通过计算找到中间画圆的每一条线的颜色组合起来就是一个渐变的效果了。

然后问题就是给你两个色值怎么计算中间的线段的颜色,其实对于rgba的颜色我们可以看到他是由四个数字组成的,那我把这四个数字分别求出四组长度相同且组内间隔相同的中间值那就可以得到颜色的中间值了,然后在搭配上张老师硬核的色值转换JS HEX十六进制与RGB,HSL颜色的相互转换那就可以实现出我们想要的效果了。

通过一个开始颜色和一个结束颜色,默认是rgba的颜色,num是分段数,就可以求出中间每一段的颜色了

  // 把颜色分段
const beginColor = begin.slice(5, -1).split(',').map(item => Number(item))
const endColor = end.slice(5, -1).split(',').map(item => Number(item))
// 分段后的颜色储存在这个数组
const middleColor = [[], [], [], []]
// 循环rgba四种
beginColor.forEach((item, index) => {
// 当前的值每段颜色之间的间隔
const differ = (endColor[index] - item) / (num - 1)
// 循环分段数的次数
for(let i = 0; i< num; i++) {
// 每次加上这个间隔
middleColor[index].push((item + differ * i).toFixed(2))
}
})
console.log(middleColor)
console.log(num)

然后绘制的话就是一段一段的画了,麻烦的地方就是计算每次从多少的角度画到多少的角度

  for(let i = 0; i< num; i++) {
ctx.beginPath()
// 这里是每次绘制的过程
// 每次绘制一段小圆弧
// 最后一段只需要画一段就好
if(i === num - 1)
ctx.arc( 150 * dpr,150 * dpr, 100 * dpr, (Math.PI * 2 * value) / num * i, (Math.PI * 2 * value) / num * (i + 1));
else
ctx.arc( 150 * dpr,150 * dpr, 100 * dpr, (Math.PI * 2 * value) / num * i, (Math.PI * 2 * value) / num * (i + 2));
ctx.lineWidth = 60;
// ctx.lineCap = "round";
ctx.strokeStyle= `rgba(${middleColor[0][i]}, ${middleColor[1][i]}, ${middleColor[2][i]}, ${middleColor[3][i]})`;
ctx.stroke();
ctx.closePath()
}

结果非常的顺利,就是自己想要的结果,具体怎么一段一段的画,怎么求出颜色的中间值看这里

优化

其实把绘制的过程放慢看

就是这个过程,每次画一段,每段不同的颜色组合起来就是一个渐变色,然后分段数再加多一点就会靠上去很流畅。

在完成后发现了几个问题,首先是在分段数很少的时候就会出现一块一块的间隔

就像这样,我大概分析了一下,猜测这个间隔出现的原因应该是我计算每一段的角度的时候肯定有除不尽的,我就四舍五入了,应该就会产生一些小间隔。

然后我就觉得把分段数提高应该就会好一些,然后就发现分段数高间隔会生成类似于摩尔纹的东西

然后就开始思考怎么去消除,最后想到了一种方案就是在每次绘制的时候绘制两段的长度,然后移动只移动一段的长度,就会下一段覆盖在上一段,就不会有间隔了,然后颜色渐变也还是一段一段的不会有影响。

然后还有一个问题就是有锯齿,不清楚,解决方案也很简单,就是把你的画布放大指定倍数,然后半径也放大同样的倍数,最后dom的高宽不变,就会让绘制的图形更加的清晰。

总结

到此这个问题就算是解决了,然后我还顺便写了一个库,大家有兴趣的可以去使用一下,我还加上了数字,动画也可以支持多段渐变gradient-ring-progress

通过这次的需求我收获到了,做东西需要完全的去了解了需求再去确定实现方案然后再动手,实现方案其实有非常多种,我们需要找到的是最合适的解决方案。最后抄袭张老师的一句话

然而一个人的积累总是有限,而创意总是无限的,因此一定还有其他更好更妙更简单的实现,欢迎分享欢迎指教!

参考资料

CSS conic-gradient()锥形渐变简介

手把手教你画圆锥渐变

JS HEX十六进制与RGB,HSL颜色的相互转换

canvas锥形渐变进度条的更多相关文章

  1. 自定义控件之圆形颜色渐变进度条--SweepGradient

    前几天在群里面有人找圆形可颜色渐变进度条,其中主要的知识点是SweepGradient: mSweepGradient = new SweepGradient(240, 360, new int[] ...

  2. html5 canvas绘制环形进度条,环形渐变色仪表图

    html5 canvas绘制环形进度条,环形渐变色仪表图                                             在绘制圆环前,我们需要知道canvas arc() 方 ...

  3. 【iOS】环形渐变进度条实现

    之前有人在找渐变进度条的效果,闲来无事就顺手写了一个,然后画了视图层级,方便讲解. 环境信息: Mac OS X 10.10.3 Xcode 6.3.1 iOS 8.3 效果图: 源码下载地址: ht ...

  4. canvas绘制圆形进度条(或显示当前已浏览网页百分比)

    使用canvas绘制圆形进度条,或者是网页加载进度条 或者是显示你浏览了本网页多少-- 由于个浏览器的计算差异,打开浏览器时 初始值有所不同,但是当拉倒网页底部时,均显示100%. 兼容性:测试浏览器 ...

  5. Canvas实现环形进度条

    Canvas实现环形进度条 直接上代码: <canvas width="200" height="200" >60%</canvas> ...

  6. iOS圆弧渐变进度条的实现

    由于项目需要一个环形渐变进度条显示课程,这方便网上的确有很多相关资料但是,都是比较零散的而且,大多数只是放一堆代码就算完了.这里我想详细写一篇我自己实现这个进度条的过程. 实现一个圆弧进度条主要分为三 ...

  7. android自己定义渐变进度条

    项目中须要用到一个弧形渐变的进度条,通过android自带是不能实现的.我是没有找到实现的方法,有大神知道的能够指点.效果图是以下这种 这是通过继承VIew来绘制出来的,网上也有相似的,可是代码那是相 ...

  8. iOS 渐变进度条

    #import <UIKit/UIKit.h> @interface JianBianView : UIView //为了增加一个表示进度条的进行,可们可以使用mask属性来屏蔽一部分 @ ...

  9. canvas绘制环形进度条

    <!DOCTYPE html> <html > <head> <meta http-equiv="content-type" conten ...

随机推荐

  1. HDU 1874 畅通工程续 2008浙大研究生复试热身赛(2)

    畅通工程续 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...

  2. 图论--2-SAT--暴力染色法求字典序最小模版

    #include <cstdio> #include <cstring> #include <stack> #include <queue> #incl ...

  3. 最新Idea超实用告别996插件,都是免费

    Idea告别996插件 在IntelliJ IDEA中,秉着IDEA自带能实现的快捷方式就不用插件的原则,少用些插件,运行性能也提升一些,虽然很少,哈哈.分享下我个人常用的插件,希望对大家有些帮助.插 ...

  4. 8) drf 三大认证 认证 权限 频率

    一.三大认证功能分析 1)APIView的 dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial(request, *ar ...

  5. Java——多线程超详细总结

    该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 一.线程概述 几乎所 ...

  6. P1353 Running S

    题意:https://www.luogu.com.cn/problem/P1353 奶牛们打算通过锻炼来培养自己的运动细胞,作为其中的一员,贝茜选择的运动方式是每天进行 n 分钟的晨跑.在每分钟的开始 ...

  7. CC2530入门

    一.简介 单片机(MCU)就是一个将微型计算机系统制作到里面的集成电路芯片. 微控制器的基本结构:内核+外设.内核通过寄存器控制外设:外设通过中断系统通知内核:内核与外设之间通过总线传输数据.地址及控 ...

  8. Altium Designer PCB封装bug,元件焊盘位置偏移解决方法

    1.问题描述:在拖动几个电阻位置时,意外发现Altium designer20版本软件的一个bug——0805的电阻两焊盘位置发生了偏移,如下图所示. 2.解决办法: ①选中焊盘偏移的封装,右键剪切掉 ...

  9. python第七天--文件练

    目的: 将不同人物说的话分别保存下来 以==========分段 代码: f=open('record.txt','r',encoding='UTF-8') zyf=[] smy=[] count=1 ...

  10. [hdu5249]动态中位数

    题意:3种操作分别为入队,出队,查询当前队列的中位数.操作数为1e5数量级. 思路:先考虑离线算法,可以离散+线段树,可以划分树,考虑在线算法,则有treap名次树,SBtree(size balan ...