Implementing Text Scroll Playback

To achieve text scroll playback, it can be implemented using CSS3 animation and controlled by Js. Since there are limitations when using CSS animation to control the offset, it is usually implemented using Js.

Implementation

CSS Animation

Using the CSS animation method, the position: relative property is used in conjunction with the left property to control the relative offset of the text element from the left side. The main issue with this method is that left is relative to the width of the parent element when set to 100%, so the value of this property depends on the width of the parent element and the width of the text content itself.

<!DOCTYPE html>
<html>
<head>
    <title>CSS Animation</title>
    <style type="text/css">
        .container{
            border: 1px solid #eee;
            overflow: hidden;
            display: inline-block;
        }
        @keyframes text-scroll {
            0% {
                left: 100%;
            }
            25% {
                left: 50%;
            }
            50% {
                left: 0%;
            }
            75% {
                left: -50%;
            }
            100% {
                left: -100%;
            }
        }
        .text {
            position: relative;
            animation: text-scroll 5s linear infinite;
        } 

    </style>
</head>
<body>
    <div class="container">
        <div class="text">循环滚动播放滴滴答答滴滴答答滴滴答答</div>
    <div>
</body>
</html>

Using the CSS animation method, the transform: translateX() property is used to control the relative offset of the text element from the left side. This method also has the same issue mentioned above.

<!DOCTYPE html>
<html>
<head>
    <title>CSS Animation</title>
    <style type="text/css">
        .container{
            border: 1px solid #eee;
            overflow: hidden;
            display: inline-block;
        }
        @keyframes text-scroll {
            0% {
                transform: translateX(100%);
            }
            50% {
                transform: translateX(0);
            }
            100% {
                transform: translateX(-100%);
            }
        }
        .text {
            animation: text-scroll 5s linear infinite;
        }
</style>
</head>
<body>
    <div class="container">
        <div class="text">Tick tock, tick tock, tick tock</div>
    <div>
</body>
</html>

JavaScript

With JavaScript, we can achieve seamless scrolling by duplicating the element and placing it behind the original element. When the first element finishes scrolling, we immediately reset its position.

<!DOCTYPE html>
<html>
<head>
    <title>Javascript</title>
    <style type="text/css">
        .container{
            display: flex;
            border: 1px solid #eee;
            overflow: hidden;
            text-overflow: ellipsis;
            width: 150px;
        }
        .text{
            padding: 0 5px;
            white-space:nowrap;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="text">Tick tock, tick tock, tick tock</div>
    <div>
</body>
<script type="text/javascript">
    (function(win, doc){
        const container = doc.querySelector(".container"); // Container element
        const textNode = doc.querySelector(".container > .text"); // Text element
        container.appendChild(textNode.cloneNode(true)); // Duplicate the element and place it behind
        const textWidth = textNode.offsetWidth; // Get the width of the text element
        let count = container.offsetWidth; // Initialize the left offset to the size of the container
        const loop = () => {
            if(count <= -textWidth) { // If the text offset exceeds the width of a text element, reset it
                textNode.style["margin-left"] = 0; // Reset
                count = 0; // Reset
            }
            textNode.style["margin-left"] = `${count--}px`; // Continue moving to the left
            window.requestAnimationFrame(() => loop()); // Recursive animation call
        }
        window.requestAnimationFrame(() => loop()); // Start the animation
        // requestAnimationFrame pauses rendering when the page is not active, so it will continue from where it left off when the page is activated. setInterval needs to be cleared and reset using the visibilitychange event listener.
    })(window, document);
</script>
</html>

Daily Question

https://github.com/WindrunnerMax/EveryDay

Reference

[Click here to read the article](https://zhuanlan.zhihu.com/p/101107612)