首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

使用SVG制作进度条之二

在上一节中,学习了怎么利用SVG的和来制作进度条。记得在文章末尾留了一个悬念,说这一节中,要聊聊怎么用Vue来把这个SVG的进度封装成组件。

咱们先不聊Vue怎么把这个封装成组件(我搜索了一下,有现在所这方面组件,而且做得蛮好的,接下来先学习一下)。今天接着聊上一节中的进度条怎么来实现。不过略有不同。不同点来自于网上一位朋友向我提的一个问题。问题是这样的:

用SVG做一个环形的进度条一样的东西,这个很好做(用的 ),但是,我需要再做一个小圆,随着环形慢慢变成一个圆时一直和头部在一起移动(这个不懂)。这个能稍微指点一下我吗?

说实话,我也很好奇!但我想在以前的基础上添加一个,让这个新添加的跟着内圈做位移(旋转),应该是可以的。也正因为出于好奇,给他找了两个Demo(Demo1、Demo2) 。原本应该能满足其需求。但并不是这样,他希望不借用第三方的库。后来回来自己写了一个 Demo。简单的记录一下这个过程。

简单的分析一下

不管是水平的还是圆形的,其都具有三层,比如下图所示:

灰色表示进度条的底层(总共的长度)

红色表示进度条的进度 (已完成长度)

绿色表示起点 (跟随圆点)

在SVG中的话,对应的就是:

水平进度条,灰色和红色是由元素构建,绿色的由构建

圆形进度条由三个构建

知道其中的原委,那就好办的得多了。咱们可以先绘制一个静态的图出来:

这个时候看到的效果如下:

从效果中,可以看出来,现在绿色的圆点都在默认的起点。并没有跟随进度条红色的部分。在SVG中并没有直接的方法或者API来让绿色点保持在红色点的终点。这个时候咱们需要借助CSS的特性来完成。这也离不开一些数学的计算。具体怎么来计算呢?先来看水平进度条。

通过前面的学习,知道使用可以知道其长度。在这个示例中,通过:

document.querySelectorAll('line')[].getTotalLength()// => 170

可以知道整个水平进度条的总长度是,而红色的进度是通过值来控制的,在这个示例中是。有了这两个值,就很好的控制绿色的值了。使用CSS的来做对应的位移,其位移的值是,即。

在行内添加了,当然你也可以在CSS样式中写。这个时候你看到的效果如下:

上面完成了水平进度条的效果,接下来看圆形进度条。对于圆形的进度条,我们同要要知道其长度,同样可以能过来获取:

document.querySelectorAll('circle')[2].getTotalLength();// =>464.2044677734375

建议上向上取整,此时我们的周长是。除此之外,还可以通过来计算。

因为圆形进度条是一个圆,那么通过是无法实现的,这个时候,需要使用的是中的来旋转。既然需要旋转就需要一个角度值。那又得数学公式了。简单的回忆一下:

弧度 = 角度 * Math.PI /180=> rad = (π /180) * deg角度 = 弧度 *180/ Math.PI => deg = (rad *180) / π

其实就是角度()和弧度()之间的转换。一个完整的圆的弧度是,所以,,,(约)。以度数表示的角度,把数字乘以便转换成弧度;以弧度表示的角度,乘以便转换成度数。

角所对的弧长是半径的几倍,那么角的大小就是几弧度

平时我们常看到的各种弧度如下:

通过JavaScript可以来这样进行角度和弧度之间的换算:

rad =(Math.PI * deg) /180deg =(rad *180) / Math.PI

下图展示了常见的角度和弧度之间的换算:

回到我们的示例当中来。通过可以获取圆角的长度约为,对应红色圆的值为。那么就能获取到红色进度的弧长为。前面说过,角所对的弧长是半径的几倍,那么角的大小就是几弧度:

65 / 74 = .87rad

另外也可以将换成。根据前面的计算公式,可以计算出来:

大约。那么在元素中添加:

transform:rotate(.8783783783783784rad);transform-origin: 100px120px;

这个时候看到的效果如下:

特别声明:SVG的坐标系统和Web中的坐标系统是不一样的,所以需要对元素做坐标变换,也就有了的设置。

添加动画效果

SVG中改变的值,可以实现线条自画的效果。这并不是什么新东西,也不是复杂的东西。在我们今天的示例当中的关键点是怎么当绿色的点跟着移动。

通过前面的了解,在水平进度条中,需要给一个值,而这个值是:

.getTotalLength() - stroke-dashoffset

对于圆形的稍为复杂一点,其要给传一个值:

(.getTotalLength() - stroke-dashoffset) / r;// => 弧度值

或者:

(.getTotalLength() - stroke-dashoffset) / r *180/ Math.PI;=>角度值

既然知道其中原理,我们就来换成Vue的环境。把红色的绑定一个数据,然后使用来动态修改的值。并且动态修改绿色圆点的位置或者旋转值。比如:

line: stroke-dashoffset = "{}"

circle:stroke-dashoffset = "{}"

对应的Vue代码:

letapp =newVue({ el:'#app', data () {

return{ dashOffsetCircle:400, dashOffsetLine:90, } }, methods: { moveLine:function(e){letcircleLine = document.getElementById('circle')

letlineInnerLen = document.getElementById('lineInner').getTotalLength() circleLine.style.transform="translateX("+ (lineInnerLen - e.target.value) +"px)"}, moveCircle:function(e) {

letcircleInner = document.getElementById('circleInner')

letcircleInnerLen = Math.ceil(document.getElementById('circleInner').getTotalLength())

letarcLen = circleInnerLen -this.dashOffsetCircle

letrad = arcLen /74circleInner.style.transform="rotate("+ rad +"rad)"} }})

Vue代码写得比较拙逼,路过的大婶请多多指点。这个时候,你拖动,改变其值时,就可以看到对应的效果。

事实上除了使用元素和元素之外,还可以使用元素来实现类似的效果。感兴趣的同学,不仿使用来做一个。如果做了,记得在下面的评论中与一起分享您的成果。

总结

这篇文章主要在上一节的基础上添加了一个网友想要的效果。就是在进度条上有一个圆点,能跟随进度条一起移动。其实现原理并不复杂。对于水平进度条,通过来改变其位移的位置,对于圆形进度条,则通过旋转来改变其位置。不管是哪一种,都需要动态的计算出他们的值,然后修改对应元素的样式。很多时候CSS和SVG的结合能让我们做出一些意想不到的效果。如果你感兴趣的话,不仿一试。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180127B015A000?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券