简单的实现文字滚动效果

8,178 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

文字超出一般都是换行或者截断隐藏改成省略号,但是类似公告的文字提示必须完整的展示出来。这种一般会让文字滚动起来,以便用户看到完整的信息。本文记叙了一种比较简单的实现方法。

效果

基本思路

实现文字滚动的难点在于,无论使用何种方式,都绕不开判定文字的实际宽度。
虽然使用transform: translateX可以绕过确定文字区域宽度的步骤,因为translateX可以接受百分比数值,如果设置translateX(-100%)就是意味着把整个元素向左移动整个元素本身宽度的距离;结合animation,可以使用循环滚动。
但是动画执行时间的确定还是需要获取文字的实际宽度,因为实际应用中,滚动的文字不是一尘不变的,因此动画的执行时间不能固定成一个值;真正的执行时间应该是文字长度 / 滚动速度

代码

HTML布局

基本上需要两个元素,一个确定展示区域,一个确定需要滚动的位置:

<div class="box">
  <div class="content">
    滚动内容.....
  </div>
</div>

其中.box表示展示的区域,确定了展示文字的区域,.contentinnerText是需要滚动的文字。

基本样式

  1. .box需要确定展示区域的宽度width, 同时禁止子元素超出区域, 用于隐藏超出的文本;
  2. .content中设置文字超出不换行, 让所有文字都在同一行上; 同时因为.contentdiv, 所以会自动继承父级元素的宽度, 在这种情况下设定translateX(-100%)自会向左移动父级元素宽度的距离, 而不是文本长度的距离, 所以需要将.content的宽度设置为内容的最大宽度max-content, 或者让.content通过浮动float或绝对定位position: absolute来脱离文本流, 不继承父级宽度, 让内容撑开宽度。 样式如下:
.box {
  width: 398px;
  height: 40px;
  line-height: 40px;
  background: #a5b4fc;
  color: #fff;
  overflow: hidden;
}

.content {
  white-space: nowrap;
  width: max-content;
}

效果: 微信截图_20220611163724.png 可以看到基本的摆放效果已经没问题了。

添加动画

定义一个动画, 使用transform: translateX来设定.content的移动, 动画如下:

@keyframes roll {
  0% {
    transform: translateX(380px);
  }
  100% {
    transform: translateX(-100%);
  }
}

注意: 动画在开始的时候, 让.content向右移动.box宽度的距离, 这样所有的文字都在展示区域的右侧, 用户看不到文字, 最后执行到transform: translateX(-100%)时, 所有文字都在展示区域的左侧, 用户同样看不到文字; 这样重复执行动画时, 用户看上去像是无缝滚动。 最后将动画效果添加到.content, 就可以看到效果了: 动画1.gif

计算动画执行时间

这个比较简单,获取文字元素,用于获取文本的实际宽度和设定动画执行时间:

const contentEl = document.querySelector('.content')

设定速度,经过多次调整,个人觉得比较适合的速度是110px/s,这个因人而异:

const speed = 110

随后就是给文本元素添加动画执行时间:

contentEl.style.animationDuration = contentEl.clientWidth / speed + 's'

至此,一个完整的文字滚动效果就完成了。