这篇文章发布于 2015年07月31日,星期五,22:20,归类于 SVG相关。 阅读 109883 次, 今日 10 次 30 条评论
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=4889
一、无题
如题。
于2017年11月2日新增案例
实际项目开发时候,设计师设计的还原可能不是下面这种纯色的圆环,而是一种复合渐变效果,类似下图:
也是可以实现的,原理是使用两个渐变半圆无缝叠加在一起就可以了。
完整案例(含10秒倒计时JS代码),可狠狠地点击这里体验:SVG与多彩渐变圆环倒计时效果demo
其中SVG中使用了3个<circle>
,如下截图:
分别表示底部灰色完整圆环,左半渐变圆环和右半渐变圆环。
二、历史正文
设计师设计了一个图片上传圆环loading进度效果。如下截图:
首先,CSS3是可以实现的,以前写过一篇转大饼的文章:“CSS3实现鸡蛋饼饼状图loading等待转转转”。原理跟这个一模一样,两个半区的矩形,然后不同时机巧妙显隐实现。
但是呢,CSS3实现不太好理解,进度控制也不容易,最好直接数值变一变,进度效果就出来。
有没有其他方法呢?
哈,当然有,可以使用同样IE9+支持的SVG.
我们只需要一个实线背景圆,一个虚线变化圆两个圆就可以了。
百闻不如一见,您可以狠狠地点击这里:SVG实现圆环loading进度效果demo
拖动demo下面的range区域选择控件(0-100%)就会发现蓝色高亮圆环跟着一起变化了:
SVG代码非常简单,如下示意:
<svg width="440" height="440"> <circle cx="220" cy="220" r="170" stroke-width="50" stroke="#D1D3D7" fill="none"></circle> <circle cx="220" cy="220" r="170" stroke-width="50" stroke="#00A5E0" fill="none" transform="matrix(0,-1,1,0,0,440)" stroke-dasharray="0 1069"></circle> </svg>
其中,上面红色加粗的就是效果实现的关键。
stroke-dasharray
在SVG中表示描边是虚线,两个值,第一个是虚线的宽度,第二个是虚线之间的间距。下面就是一些虚线数据值以及最后的效果表现(实时,非截图,IE9+浏览):
<?xml version="1.0"?> <svg width="200" height="200" viewPort="0 0 200 300" version="1.1" xmlns="http://www.w3.org/2000/svg"> <line stroke-dasharray="5, 5" x1="10" y1="10" x2="190" y2="10" /> <line stroke-dasharray="5, 10" x1="10" y1="30" x2="190" y2="30" /> <line stroke-dasharray="10, 5" x1="10" y1="50" x2="190" y2="50" /> <line stroke-dasharray="5, 1" x1="10" y1="70" x2="190" y2="70" /> <line stroke-dasharray="1, 5" x1="10" y1="90" x2="190" y2="90" /> <line stroke-dasharray="0.9" x1="10" y1="110" x2="190" y2="110" /> <line stroke-dasharray="15, 10, 5" x1="10" y1="130" x2="190" y2="130" /> <line stroke-dasharray="15, 10, 5, 10" x1="10" y1="150" x2="190" y2="150" /> <line stroke-dasharray="15, 10, 5, 10, 15" x1="10" y1="170" x2="190" y2="170" /> <line stroke-dasharray="5, 5, 1, 5" x1="10" y1="190" x2="190" y2="190" /> <style><![CDATA[ line{ stroke: black; stroke-width: 2; } ]]></style> </svg>
之前写了篇“纯CSS实现帅气的SVG路径描边动画效果”,就是stroke-dasharray
的妙用。
这里也是类似原理。
理解了stroke-dasharray
,我们的事情就简单了,我们只需要让间距永远不小于圆的周长,然后,虚线的长度 = 百分比值 * 圆的周长就可以了。
简单,超乎想象:
// 假设周长是1068, percent是百分比值
circle.setAttribute('stroke-dasharray', 1068 * percent + " 1069");
就OK了。
哦~~差点忘了。默认stroke-dasharray
的起始位置在右侧,而不是上方,因此,偶们需要使用transform
逆时针旋转90°, 这就是第二个circle
元素上面transform="matrix(0,-1,1,0,0,440)"
的由来。
更新于2016年11月24日
测试发现,iOS 手机上,貌似transform
逆时针旋转90°只会改变图形外观,但是其坐标起始位置还是右侧。因此,更改起始坐标可能还需要通过外部容器旋转控制。
更新于2017年11月1日
感谢辉辉的反馈,iOS手机上起始坐标异常问题,可以通过添加如下CSS修正:
svg { -webkit-transform: rotate(-0.05deg); transform: rotate(-0.05deg); }
三、结语
目前越来越多移动端图标展示需求,很多开源图表框架的问题在于,体积大,UI很难改变,无法满足设计需求。且一般移动端的展示都比较简单,此时,使用简单的SVG实现是性价比最高的方式。
所以,好好学学SVG,比追逐热点更受益。
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:http://www.zhangxinxu.com/wordpress/?p=4889
(本篇完)
- 纯CSS实现帅气的SVG路径描边动画效果 (0.510)
- CSS var变量的局部作用域(继承)特性 (0.327)
- 更好的纯CSS滚动指示器技术实现 (0.327)
- 妙法攻略:渐变虚框及边框滚动动画的纯CSS实现 (0.163)
- 浏览器IMG图片原生懒加载loading="lazy"实践指南 (0.163)
- 使用navigator.connection.downlink前端测网速 (0.163)
- 我使用CSS模拟个假的数字loading效果 (0.163)
- 聊聊Web网页中资源加载的优先级 (0.163)
- 使用SVG实现gradient背景渐变 (0.019)
- 了解:使用CSS namespace进行分隔 (0.019)
- SVG图标颜色文字般继承与填充 (RANDOM - 0.019)
viewbox 应改为 viewBox
请问那里可以系统的学习svg动画的教程
这里的周长怎么计算,这个半径不太对。
要让间距永远不小于圆的周长 上面又写了周长*(1-百分比)。这个样子的话 那间距乘以一个比1小的数 永远小于本身 也就是周长啊,这不是矛盾吗,本来这里有点迷糊,这下子更迷糊了,求解答~
我懂了大概
第一幅图的js地址在哪啊
针对iOS控制起始位置从正午12点的位置,本人多次测试,下面的方法有效.同时兼容android.
.test {
-webkit-transform: rotate(-0.05deg);
transform: rotate(-0.05deg);
transform-origin:center center;
}
希望帮到遇到同样问题的朋友!
transform不生效时,加一度就可以了 rotate(-91deg)
svg viewBox属性必须大写,要不然无法随父级大小变化,不要问我怎样知道的,坑了太久时间
回复:更新于2016年11月24日
测试发现,iOS 手机上,貌似transform逆时针旋转90°只会改变图形外观,但是其坐标起始位置还是右侧。因此,更改起始坐标可能还需要通过外部容器旋转控制。
这个是错的,你把外部容器旋转90°也没用,可用的方法为:
-webkit-transform: rotate(-89.95deg);
transform: rotate(-89.95deg);
transform-origin:center center;
为什么90°的时候不起作用,而89.95°却有用,谁能解释下?
这个圆形可以,不过没有箭头不直观,需要加上箭头和百分比就好了。就是在动画跑的时候加上箭头方向(转动的方向)
谢谢大师,做app下载的时候参考了大师的loading效果。发现起始位置从最右侧变到最上方可以用stroke-dashoffset这个属性。
Hi, 亲, 发现当为 stroke-dasharray:0 2*Math.PI*R 时会出现有一条线,
解决办法:特殊判断下 当为0 时,让第二个circle 标签不出现。
http://jsbin.com/merifabefo/edit?html,js,console,output
解决了我一个bug
张大师,有一段代码按照你写的例子,在ios10测试上面不兼容,ios7,8,9都是正常的,主要是无法旋转,transform不起作用,麻烦看一下,能不能邮箱回复我一下,很着急,谢谢
.test {
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
IOS 中设置默认stroke-dasharray的起始位置在上方,可是没有效果,结果还是在默认的右方,android就没有问题
是的, 我也发现了这个问题,解决办法是起始位置在上方稍微给点偏差。
.test {
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
-webkit-transform: rotate(269deg);
transform: rotate(269deg);
}
大师,请问第二个circle元素旋转时圆心是什么啊?用rotate可以么?可是我试过之后不可以,不知道为什么,麻烦大师解答。
您好,我尝试将这个环形进度封装成一个组件,在页面中显示下载进度。
如果页面中只有一个应用,是可以的。
但在一个应用列表页,如何才能做到各个应用的下载进度互不影响呢?
望回复,谢谢
在iphone的safari中,translate旋转进度条的开始位置不能生效。
transform=”matrix(0,-1,1,0,0,440)”
这一句在Safari中不生效
改成rotate(-90, 220, 220)就可以了
在手机上显示不一样,蓝色圈圈开始的起点是下午3点,而不是正午12点
很不错的样子!
建议稍加封装,作为开源的组件发布出来,那样大家用起来岂不是更爽!
请问这个圆环能做成渐变的吗,搜了stroke没找到可以设置渐变的方法,求指教,谢谢
楼主文章中说:
// 假设周长是1068, percent是百分比值
circle.setAttribute(‘stroke-dasharray’, 1068 * percent + ” 1069″);
但demo里的代码却是:
circle.setAttribute(‘stroke-dasharray’, perimeter * percent + ” ” + perimeter * (1- percent));
一开始我一头雾水,stroke-dasharray的最后一个值完全没有必要设置成动态的吧?不过这两个都可以实现效果。
@qinqing 对的,定值就可以。动态值也是支持的。
冒个泡
不错
不错!
帅,一直不知道怎么做的之前。