[英]Marquee text effect. Same scrolling speed no matter the length of the text
我的网站上有一个类似于选取框的元素,它从屏幕的右侧滑到左侧。 html 看起来像这样:
<div class='text-scroller-container'>
<p class='message'></p>
</div>
滚动条内可以有许多不同的消息。 有些范围从一个单词到一个完整的句子。
我处理滚动的方式是设置left: 100%
并添加一个transition: left 5s
。 然后在js中将left设置为0。
我现在面临的问题是超短消息滚动非常慢,而非常长消息滚动快速,因为它们都绑定到5s transition duration
。
我确定有一种方法可以计算相对于元素offsetWidth
的速度,以便无论消息的长度如何,它都以大致相同的速度滚动。
我最初的解决方案是使用setInterval/requestAnimationFrame
并一次移动元素 1px 直到其宽度完全离开屏幕。 但是,我现在需要提高我的 web 应用程序的性能,所以我要切换回使用过渡。
这个事情谁有经验?
这听起来更像是 animation,而不是过渡。 当 state 发生变化时,转换只运行一次,而 animation 可以永远循环,从而产生选框效果。
您需要的是一个 animation 循环。 您可以使用CSS Keyframes来做到这一点。 使用它,您可以指定开始和结束 state,然后无限循环这些状态。
现在这里的问题是速度。 需要计算速度。 CSS 不能这样做,所以我们需要添加一些 JavaScript 来解决这个问题。
速度的计算是amount of pixels per second * (width of message + container width)
。 所以在一段时间内行进的距离乘以距离。 消息越大,持续时间越长。
下面的示例显示了三个选框,每个选框都有不同长度的不同消息。 JavaScript 循环遍历每条消息,进行计算,并为每条消息设置animationDuration
持续时间(以毫秒为单位)。
/** * The speed in time (in milliseconds) of a single pixel. * Changing this value will change the speed. * @type {number} */ const timePerPixel = 20; /** * Width of the container. * Hardcoded for simplicity' sake. * @type {number} */ const containerWidth = 200; /** * Select all the messages * @type {NodeList} */ const messages = document.querySelectorAll('.message'); /** * For each message, calculate the duration based on the lenght of the message. * Then set the animation-duration of the animation. */ messages.forEach(message => { const messageWidth = message.offsetWidth; const distance = messageWidth + containerWidth; const duration = timePerPixel * distance; message.style.animationDuration = `${duration}ms`; });
.text-scroller-container { position: relative; width: 200px; height: 20px; border: 1px solid #d0d0d0; border-radius: 3px; background-color: #f0f0f0; overflow: hidden; margin-bottom: 10px; }.message { display: block; position: absolute; top: 0; right: 0; margin: 0; white-space: nowrap; /* Starting postition */ transform: translate3d(100%, 0, 0); /* Animation settings */ animation-name: marquee-animation; animation-iteration-count: infinite; animation-timing-function: linear; } @keyframes marquee-animation { from { /* Start right out of view */ transform: translate3d(100%, 0, 0); } to { /* Animate to the left of the container width */ transform: translate3d(-200px, 0, 0); } }
<div class='text-scroller-container'> <p class='message'>This is a sentence. I'm a long sentence.</p> </div> <div class='text-scroller-container'> <p class='message'>This is a short sentence.</p> </div> <div class='text-scroller-container'> <p class='message'>This is a very long sentence. This sentence is going to be the longest one of them all.</p> </div>
如果您正在寻找高性能动画,请使用transform
属性而不是left
。 虽然left
更改将重新绘制整个页面,但transform
只会重新渲染受转换影响的部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.