路径动画的效果仍是挺有意思的,而 Web 中经常使用的方法就是 SVG。
先上一个效果图:
javascript
要在 SVG 里面实现文字路径动画仍是比较简单的,SVG 里面就有自然的支持。css
咱们先搞个 SVG 路径html
<svg id="textPathDemo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="960" viewBox="0 0 581 120">
<path stroke="#FF4444" d="M62.9 14.9c-25-7.74-56.6 4.8-60.4 24.3-3.73 19.6 21.6 35 39.6 37.6 42.8 6.2 72.9-53.4 116-58.9 65-18.2 191 101 215 28.8 5-16.7-7-49.1-34-44-34 11.5-31 46.5-14 69.3 9.38 12.6 24.2 20.6 39.8 22.9 91.4 9.05 102-98.9 176-86.7 18.8 3.81 33 17.3 36.7 34.6 2.01 10.2.124 21.1-5.18 30.1" fill="none" stroke-width="1" stroke-dasharray="5 5" id="text-path1"></path>
<text>
<textPath xlink:href="#text-path1" class="text-content" textLength="160" startOffset="160">
SVG 文字路径动画
</textPath>
</text>
</svg>复制代码
这里的 path
就是用来定义路径的,这个路径我是网上找的,通常作的话能够用 AI 等 SVG 制做工具,几个关键属性介绍一下。前端
stroke-dasharray 表示用虚线描边。可选值为none, , inherit。java
inherit 表示继承node
这个属性颇有用,基本上 SVG 动画都须要用到,这是一个逗号或者空格分隔的数值列表,第一个值表示线段的长度,第二个值表示线段间空白的长度,例子中 stroke-dasharray="5 5"中,第一个 5 表示虚线中的线段的长度,而第二个 5 表示两个线段间的长度是 5px。因此出来的效果是每段虚线的间隔都是同样的。其实这个dasharray能够不仅两个值,能够有不少个,会循环依次用到线段和空白之间。css3
stroke,stroke-width 分别表示描边长度和描边宽度,这里就是改颜色用的。git
这里比较关键的是 textPath
这个节点,这里就是定义文字按照什么路径排列的。程序员
其中主要的属性:github
path
那设置的 id 属性。如今出来的效果是这样的:
如今还没动,要让它动起来很简单,上面咱们介绍了 startOffset
属性表示文字起始点,只要改变这个起始点就能够动了。
因而咱们来加点 javascript:
var txtEle = $(".text-content");
var rafId = null;
var isEnd = false;
var animateFunc = function(start, step, end){
var startOffset = start + step;
if (startOffset >= end){
startOffset = end
isEnd = true;
}
// txtEle.attr("startOffset", startOffset); // not work
txtEle[0].setAttribute("startOffset", startOffset);
if(isEnd){
cancelAnimationFrame(rafId);
return;
}
requestAnimationFrame(function(){
animateFunc(startOffset,step,end);
})
}
var steps = Math.round( 5000/16.7 ); // 5000 means 5s
var len = 830;
var step = len / steps;
animateFunc(-160, step, len);复制代码
代码比较简单,可是有几个地方我要说明一下。
首先是我把 jQuery 里面设置的 attr
的方法 txtEle.attr("startOffset", startOffset);
注释了,由于 jq 会把属性用小写写到元素里面,而这里的 startOffset
恰恰是大小写敏感的,因此要改用 dom 的 setAttribute
方法。
而后,这段代码里面有几个地方写的是 hard code,好比 var len = 830;
,中的 830,animateFunc(-160, step, len);
中的 -160。
这里 830 表示的是文字要走的路径的长度,这 830 是我大概算出来的,由于咱们想文字停在最后那里,而不是跑出去,计算方法是路径的长度减去文字长度,固然这个值不是很准确。
animateFunc(-160, step, len);
中的 -160 表示的是文字起始点,由于咱们想有个进场效果,而不是全部文字一开始就排在起始点,因此要负出去,而 160 是我大概算的文字长度,这里也不许确。
写完这段 js,发现本身兜了个大圈。以前在 一个比想象中更骚气的圆-svg实现 一文中介绍过 SVG 的 animate
标签,若是只是单纯的动,这里大能够用 animate
来作。
添加 animate
到 textPath
中:
<textPath xlink:href="#text-path1" class="text-content" textLength="160" startOffset="-160">
SVG 文字路径动画
<animate attributeName="startOffset" from="-160" to ="830" begin="0s" dur="5s" repeatCount="1"/>
</textPath>复制代码
这里 attributeName表示动画属性是 startOffset,begin 表示开始的延时,dur 表示时间整个动画的时间,frome 和 to 表示初始值和最终值,repeatCount 表示重复次数,这里是 1 次,若是用 indefinite 表示无限次。只是加这个进去,是没有停在最后的样式的,作完一次,字就不见了。这里 from 和 to 也能够用 0% 和 100% ,这样就没有进场效果。这个节点虽然好用,可是仍是比较适合无限循环运动的场景。
这里要想精细的控制,仍是要靠 js。
可是,做为一个要弄懂这是什么,从哪里来,到哪里去的程序员,面对代码中不少半猜半算的值,是不能视而不见的,并且路径什么的如今都是写死的,弊端略大,因而咱们能够借助一个强大的库,snap.svg.js。
Snap.svg 是一个强大的 SVG 操做库,提供了丰富的接口,惟一的问题是,你须要了解熟悉 SVG 的基础知识。
引入 Snap.svg 以后,咱们的 html 代码能够变得比较简单:
<svg id="textPathDemo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="960" viewBox="0 0 581 120">
</svg>
<script src="http://cdn.bootcss.com/snap.svg/0.4.1/snap.svg-min.js"></script>复制代码
就留一个 SVG 元素就好。
而后咱们就开始利用 Snap.svg 帮咱们干活。
window.onload = function () {
var path = "M62.9 14.9c-25-7.74-56.6 4.8-60.4 24.3-3.73 19.6 21.6 35 39.6 37.6 42.8 6.2 72.9-53.4 116-58.9 65-18.2 191 101 215 28.8 5-16.7-7-49.1-34-44-34 11.5-31 46.5-14 69.3 9.38 12.6 24.2 20.6 39.8 22.9 91.4 9.05 102-98.9 176-86.7 18.8 3.81 33 17.3 36.7 34.6 2.01 10.2.124 21.1-5.18 30.1";
var s = Snap('#textPathDemo');
path = s.path(path).attr({ 'fill': 'none', 'stroke': '1',"stroke":"#FF4444","stroke-dasharray":"5 5"});
var pathLength = Snap.path.getTotalLength(path);
console.log(pathLength);
var txt = s.text(0,0,'SVG 文字路径动画');
var txtLength = txt.node.clientWidth;
var text = txt
.attr({ 'textpath': path, 'fill':'#003399' })
.textPath.attr({ 'startOffset': -txtLength })
.animate({ 'startOffset': pathLength-txtLength }, 5000, mina.easeinout );
};复制代码
代码不是很长,简单解释一下。
var s = Snap('#textPathDemo');
。path = s.path(path).attr({ 'fill': 'none', 'stroke': '1',"stroke":"#FF4444","stroke-dasharray":"5 5"});
var pathLength = Snap.path.getTotalLength(path);
算出路径的长度,不用猜了。var txt = s.text(0,0,'SVG 文字路径动画');
var txtLength = txt.node.clientWidth;
,这里说一下,我在 Snap 的文档中没找到怎么算文字长度的,这个是打印上面那个 txt
对象后发现的,若是有更好的方法,麻烦告知哈。var text = txt.attr({ 'textpath': path, 'fill':'#003399' })
,主要设置 textpath
。.textPath.attr({ 'startOffset': -txtLength })
这里是支持链式调用的,设置起始点为 -txtLength 是为了有文字进场效果。.animate({ 'startOffset': pathLength-txtLength }, 5000, mina.easeinout );
这里设置了要作动画的属性为 startOffset
,最后的位置为 pathLength-txtLength
即路径长度减去文字长度,动画时间 5000 毫秒,以及动画函数 main.easeinout
这个动画函数是库提供的,类比 css3 中的 easeinout
的效果,比以前咱们用匀速要生动一些。效果:
简简单单,不再用猜长度值了,文字改版的时候也不用手动计算文字长度。
产品经理跟我说文字是不会变的,我知道这是最大的谎话。
因为我对 SVG 也不是太熟悉,有些地方可能有所疏漏,有什么疑问欢迎留言,有什么写错的地方,欢迎指出哈。
SVG Demo 源码地址:github.com/bob-chen/ca…
Snap.svg Demo 源码地址:github.com/bob-chen/ca…
若是页面使用了 base 标签,可能会引发路径找不到的状况,能够参考 tips - 解决 base 标签形成 SVG 效果失效
记录一些所思所想,写写科技与人文,写写生活状态,写写读书感悟,主要是扯淡和感悟,欢迎关注,交流。
微信公众号:程序员的诗和远方
公众号ID : MonkeyCoder-Life
snapsvg.io/
javascript.ruanyifeng.com/htmlapi/svg…
www.htmleaf.com/ziliaoku/qi…
本文对你有帮助?欢迎扫码加入前端学习小组微信群: