共计 2009 个字符,预计需要花费 6 分钟才能阅读完成。
提醒:本文最后更新于 2019-09-19 15:30,文中所关联的信息可能已发生改变,请知悉!
前言
最近写了一个文字跑马灯的项目需求,刚开始用 js 写,能够完成需求。后面想着换种方式 (分别是 html 和 css) 来实现同一个需求, 以减少性能消耗。
首先,需求分析:
需求点 1. 判断文字的长度和容器的长度,如果文字长度大于容器长度则开始滚动,否则不滚动;
需求点 2. 判断滚动滚动的结束,在结束的时间点触发事件(比如: 增减样式等操作);
一、JS 实现
思路:
1. 判断文字的长度和容器的长度,如果文字长度大于容器长度,则开始滚动,否则不滚动。(offsetWidth)
2. 获取滚动条到元素左边的距离, 递归滚动, 直到滚动后的距离等于文字的长度退出递归。(scrollLeft)
如果不熟悉 offsetWidth,scrollLeft,您可以点击这里offsetWidth、scrollLeft
效果图

注释: 文字抖动现象是因为录制时间过长,ps 制作 gif 文件只能是 500 帧以下,通过降低帧率才出现了文字抖动。
代码部分
预览 Demo:JS 实现文字跑马灯
小结
js 的方式能够完美的满足子需求点 1 和自需求点 2。
判断文字和容器的长度可以通过 offsetWidth 来判断。如果文字长度大于容器长度,则开始滚动。
1 | <table class="hljs-ln"><tbody><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="1"><div class="hljs-ln-n" data-line-number="1"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="1"><span class="hljs-variable language_">window</span>.<span class="hljs-property">onload</span>=<span class="hljs-keyword">function</span> <span class="hljs-title function_">checkScrollLeft</span>(<span class="hljs-params"></span>){</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="2"><div class="hljs-ln-n" data-line-number="2"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="2"> <span class="hljs-comment">// 判断文字长度是否大于盒子长度</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="3"><div class="hljs-ln-n" data-line-number="3"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="3"> <span class="hljs-keyword">if</span>(boxWidth >= textWidth){<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>}</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="4"><div class="hljs-ln-n" data-line-number="4"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="4"> content.<span class="hljs-property">innerHTML</span> += content.<span class="hljs-property">innerHTML</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="5"><div class="hljs-ln-n" data-line-number="5"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="5"> <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.text'</span>).<span class="hljs-property">classList</span>.<span class="hljs-title function_">add</span>(<span class="hljs-string">'padding'</span>)</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="6"><div class="hljs-ln-n" data-line-number="6"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="6"> <span class="hljs-comment">// 更新</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="7"><div class="hljs-ln-n" data-line-number="7"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="7"> textWidth = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">'.text'</span>).<span class="hljs-property">offsetWidth</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="8"><div class="hljs-ln-n" data-line-number="8"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="8"> <span class="hljs-comment">// 开始滚动 触发事件</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="9"><div class="hljs-ln-n" data-line-number="9"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="9"> <span class="hljs-title function_">toScrollLeft</span>()}</td></tr></tbody></table> |
判断滚动的结束根据滚动条到元素左边的距离和文字的长度判断,如果滚动条到元素左边的距离等于文字的长度,则结束滚动。
1 | <table class="hljs-ln"><tbody><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="1"><div class="hljs-ln-n" data-line-number="1"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="1"><span class="hljs-keyword">function</span> <span class="hljs-title function_">toScrollLeft</span>(<span class="hljs-params"></span>){</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="2"><div class="hljs-ln-n" data-line-number="2"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="2"> <span class="hljs-comment">// 如果文字长度大于滚动条距离,则递归拖动</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="3"><div class="hljs-ln-n" data-line-number="3"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="3"> <span class="hljs-keyword">if</span>(textWidth > box.<span class="hljs-property">scrollLeft</span>){</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="4"><div class="hljs-ln-n" data-line-number="4"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="4"> box.<span class="hljs-property">scrollLeft</span>++</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="5"><div class="hljs-ln-n" data-line-number="5"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="5"> <span class="hljs-built_in">setTimeout</span>(<span class="hljs-string">'toScrollLeft()'</span>, <span class="hljs-number">18</span>);</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="6"><div class="hljs-ln-n" data-line-number="6"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="6"> }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="7"><div class="hljs-ln-n" data-line-number="7"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="7"> <span class="hljs-keyword">else</span>{<span class="hljs-comment">// 滚动结束 触发事件}</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="8"><div class="hljs-ln-n" data-line-number="8"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="8">}</td></tr></tbody></table> |
二、HTML 实现
效果图:

代码部分:
1 | <span class="hljs-symbol"><</span>marquee behavior="behavior" width="200" loop="2">1. 文字如果超出了宽度自动向左滚动文字如果超出了宽度自动向左滚动。<span class="hljs-symbol"><</span>/marquee> |
非常简洁的代码~、~

marquee 的 API
虽然 marquee 标签的 api 十分丰富,但是该标签在 MDN 上是这样描述的:
This feature is obsolete. Although it may still work in some browsers, its use is discouraged since it could be removed at any time. Try to avoid using it.
元素已经过时,请不要再使用。尽管一些浏览器仍然支持它,但它不是必须的。此外,使用这个元素基本上是你可以对你的用户做最糟糕的事情之一,所以请不要这样做。
所以,根据咱们 IT 圈内的紧跟文档标准的原则,对 marquee 标签,我们在项目中请尽量不要使用
三、CSS 实现
效果图

代码部分
预览 Demo: CSS 实现文字跑马灯
小结
CSS 能满足子需求点 1,能够判断什么时候开始滚动。
1 | <table class="hljs-ln"><tbody><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="1"><div class="hljs-ln-n" data-line-number="1"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="1"><span class="hljs-variable language_">window</span>.<span class="hljs-property">onload</span>=<span class="hljs-keyword">function</span> <span class="hljs-title function_">checkScrollLeft</span>(<span class="hljs-params"></span>){</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="2"><div class="hljs-ln-n" data-line-number="2"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="2"> <span class="hljs-comment">// 判断文字长度是否大于盒子长度</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="3"><div class="hljs-ln-n" data-line-number="3"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="3"> <span class="hljs-keyword">if</span>(textWidth > wrapWidth) {</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="4"><div class="hljs-ln-n" data-line-number="4"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="4"> <span class="hljs-comment">// 开始滚动 触发事件</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="5"><div class="hljs-ln-n" data-line-number="5"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="5"> text.<span class="hljs-property">style</span>.<span class="hljs-property">paddingRight</span> = <span class="hljs-string">'300px'</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="6"><div class="hljs-ln-n" data-line-number="6"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="6"> cont.<span class="hljs-property">style</span>.<span class="hljs-property">left</span> = <span class="hljs-string">"-870px"</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="7"><div class="hljs-ln-n" data-line-number="7"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="7"> }</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="8"><div class="hljs-ln-n" data-line-number="8"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="8">}</td></tr></tbody></table> |
同时,也能满足子需求点 2,判断滚动的结束。
1 | <table class="hljs-ln"><tbody><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="1"><div class="hljs-ln-n" data-line-number="1"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="1"><span class="hljs-comment">// 滚动结束</span></td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="2"><div class="hljs-ln-n" data-line-number="2"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="2"><span class="hljs-variable language_">document</span>.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">"transitionend"</span>, <span class="hljs-keyword">function</span> (<span class="hljs-params"></span>){<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">"end"</span>)</td></tr><tr><td class="hljs-ln-line hljs-ln-numbers" data-line-number="3"><div class="hljs-ln-n" data-line-number="3"></div></td><td class="hljs-ln-line hljs-ln-code" data-line-number="3">}, <span class="hljs-literal">false</span>)</td></tr></tbody></table> |
结语
回顾需求
需求点 1. 判断文字的长度和容器的长度,如果文字长度大于容器长度则开始滚动,否则不滚动;
需求点 2. 判断滚动滚动的结束,在结束的时间点触发事件(比如: 增减样式等操作);
实现方式的优劣对比
js 实现跑马灯效果 | html 实现跑马灯效果 | css 实现跑马灯效果 | |
---|---|---|---|
需求点 1 | ✔️ | ✘ | ✔️ |
需求点 2 | ✔️ | ✘ | ✔️ |
兼容性 | ✔️ | ✘ | ✘ |
如果需要满足需求,js 和 css 都能够实现。但是考虑到兼容性,css 在 ios9 以下,安卓 4.4 以下不支持,其他好的解决方案在考虑中。如果你有好的解决方案,欢迎在下方留言与我交流~
另外,css 用作单纯的展示效果用还是能优先考虑的,比如下方的 css 无缝滚动
效果图

代码部分
预览 Demo css 无缝滚动动画
所以,工具本身没有优劣之分,什么时候用什么工具。我们要有清晰的思路。