最近刚上手Electron,同时也在尝试番茄工作法来改善自己的效率,于是就开发了一个练手的Project,叫时间跨度TimeSpan,是一个将白噪音(WhiteNoise)与番茄工作法(Pomodoro)功能相结合的番茄钟。开发期间遇到了一个关于在页面上绘制一个圆环的技术问题。
说实话,一开始我也并没有觉得这个问题会成为一个值得探讨的技术点,然而在实际开发过程中却让作为一个强迫症的我倍感难受。在这里详细解释一下我的hack过程。
0x00 Canvas
TimeSpan需要在页面上绘制一个圆环来作为时间指示器。想到绘制一个圆环(Circle),我第一反应就是让<canvas>上阵。好嘛,这个简单。
设置圆环的基本属性
省略了context兼容性问题的示例代码:
ctx.beginPath();
ctx.strokeStyle = '#29292C';
ctx.lineCap = 'round';
ctx.closePath();
ctx.fill();
ctx.lineWidth = 10.0;
设置圆环进度值
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
注意事项:
- arc()函数中的角度单位是弧度,不是度数。角度与弧度的js表达式:radians = (Math.PI / 180) * degrees
- starAngle 的起始位置为右顶点,而不是上顶点😂
完整示例
发现问题
看了JSFiddle的示例之后,相信不用我说都能看到明显的问题
- 在白色背景下,绘制的圆环边缘比较模糊
- 在深色背景下,绘制的圆环边缘有锯齿边,同时通过js控制进度时,圆环贴边有散落的与圆环同色的像素点
如下图所示:
解决思路
- HiDPI Canvas Polyfill 是针对设备提出的canvas高清解决方案,但是需要引入js文件并自动识别canvas将其缩小,与需要的效果不符
- 其他博客中提到的指定宽高法,我有尝试过,锯齿边的现象有所改善,但是,并没有完美解决,仍然有白色像素点散落
- CSS3替代方案
小结
canvas思路简单,但是实际情况与预想不符,还得另谋出路😷
0x01 CSS3
上一节有提到三种解决思路,然而前两种可行性并不高,于是,canvas不行我就转投CSS3的怀抱。其实CSS3的强大一直深入我心,她能实现许多以前需要用js才能实现的黑科技。果不其然,Google一下我就找到了前人的足迹。
这里先简单介绍一下原理:
其实CSS3方法实现圆环的原理是一种三层夹心的结构,在背景环之上,使用clip属性切割圆环形成两个半圆环,再分析不同情况下的半圆环旋转角度进行重叠或遮罩,来达到需要的圆环进度效果。
具体实现参照Dolphin Wood的博客:CSS3 环形进度条
发现问题
CSS3很好地解决了锯齿边和散落像素点的问题,但是在圆环较大的情况下边缘模糊的问题依然存在,特别是进度环旋转时,遮罩环的移动能在模糊的边缘明显地看到。
小结
CSS3方案并不完美,还需另觅他法😷
0x02 SVG
也许并不了解SVG?
可缩放矢量图形(Scalable Vector Graphics,SVG)是基于可扩展标记语言(XML),用于描述二维矢量图形的一种图形格式。SVG由W3C制定,是一个开放标准。
根据以上Wikipedia的词条释义,基于XML意味着你可以像写HTML一样编写SVG,然而她同时又作为一种图形文件存在。
- 图像文件可读,易于修改和编辑(理論上如此,但實際上卻是因為各種不同的SVG檔編輯器而可能儲存成不易解讀的SVG檔案)
- 与现有技术可以互动融合。例如,SVG技术本身的动态部分(包括时序控制和动画)就是基于SMIL标准。另外,SVG文件还可嵌入JavaScript(严格地说,应该是ECMAScript)脚本来控制SVG对象
- SVG图形格式可以方便的建立文字索引,从而实现基于内容的图像搜索
- SVG图形格式支持多种滤镜和特殊效果,在不改变图像内容的前提下可以实现位图格式中类似文字阴影的效果
- SVG图形格式可以用来动态生成图形。例如,可用SVG动态生成具有交互功能的地图,嵌入网页中,并显示给终端用户
再来看看有哪些浏览器支持 SVG(Basic Support)
嘛,就用她来完成圆环指示器的编写吧!
示例代码
小结
SVG完美解决了上述问题,就是她了!
总结
既然完美解决了问题,为什么又是Not Perfect Edition呢?
因为,IE对SVG的支持并不好,如图:
还好,IE上的一些bug并不影响我的需求。
So,that’s it.