简体   繁体   English

实现无限文字微调,从下往上旋转文字动画

[英]Achieve infinite text spinner, spinning text from bottom to top animation

I'm trying to implement an infinite from bottom to top spinning wheel.我正在尝试实现从底部到顶部的无限旋转轮。 So far I got the following:到目前为止,我得到了以下信息: 纺车示例

What's working:什么工作:

  1. It's spins from bottom to top它从下到上旋转
  2. It starts with the first string again after reaching the end到达结尾后再次从第一个字符串开始

What I want/what's incorrect:我想要什么/什么是不正确的:
I want the animation to be infinite, in other words, there's supposed to be no transition.我希望动画是无限的,换句话说,应该没有过渡。 When the animation reaches its last element, it must not jump back to its first, but smoothly attach it to its bottom to create a ongoing from bottom to top animation .当动画到达它的最后一个元素时,它不能跳回它的第一个元素,而是将它平滑地附加到它的底部以创建一个从底部到顶部持续动画

How can I implement such behavior?我怎样才能实现这种行为? To achieve the given effect I used js - do I need some more js or fall back to plain css animation?为了达到给定的效果,我使用了 js - 我需要更多的 js 还是回退到纯 css 动画?

class Spinner extends Component {

    state = {
      active: 0
    };

    interval;

    componentDidMount() {
        this.interval = setInterval(() => {
            this.setState({active: this.state.active === this.props.content.length - 1 ? 0 : this.state.active + 1});
        }, 1000);
    }

    componentWillUnmount() {
        clearInterval(this.interval);
    }

    setPosition = () => {
        const n = 100 / this.props.content.length;
        return n * this.state.active * -1;
    };

    render() {
        const style = {
            transform: 'translateY(' + this.setPosition() + '%)'
        };

        return (
            <div className="spinner--list d-inline-block align-self-start">
                <ul className="p-0 m-0" style={style}>
                    {
                        this.props.content.map((item, index) => {
                            return (
                                <li key={index}>
                                    <h1>{item}</h1>
                                </li>
                            );
                        })
                    }
                </ul>
            </div>
        );
    }

}
.spinner--list {
    max-height: calc((10px + 2vw) * 1.5);
    overflow: hidden;
}

.spinner--list ul {
    list-style-type: none;
    transition: transform 1s;
    will-change: transform;
}

.spinner--container h1 {
    font-size: calc(10px + 2vw);
    line-height: 1.5;
    margin: 0;
}

CSS solution by @keyframes @keyframes CSS 解决方案

 body { color: black; padding: 0; margin: 0; } .text { padding: 20px 0; display: flex; position: relative; } .item-1, .item-2, .item-3 { position: absolute; padding: 20px 0; margin: 0; margin-left: 5px; animation-duration: 4s; animation-timing-function: ease-in-out; animation-iteration-count: infinite; } .item-1{ animation-name: anim-1; } .item-2{ animation-name: anim-2; } .item-3{ animation-name: anim-3; } @keyframes anim-1 { 0%, 8.3% { top: -50%; opacity: 0; } 8.3%,25% { top: 0%; opacity: 1; } 33.33%, 100% { top: 50%; opacity: 0; } } @keyframes anim-2 { 0%, 33.33% { top: -50%; opacity: 0; } 41.63%, 58.29% { top: 0%; opacity: 1; } 66.66%, 100% { top: 50%; opacity: 0; } } @keyframes anim-3 { 0%, 66.66% { top: -50%; opacity: 0; } 74.96%, 91.62% { top: 0%; opacity: 1; } 100% { top: 50%; opacity: 0; } }
 <div class="text">This is a <div class="items"> <p class="item-1">test.</p> <p class="item-2">bug.</p> <p class="item-3">fail.</p> </div> </div>

Here's a solution without ul and with automatic adjustment to a variable number of texts you want to spin.这是一个没有ul的解决方案,可以自动调整到您想要旋转的可变数量的文本。 The solution uses keyframes and a little trick/illusion in CSS to create an infinite spinning animation on only two span -s.该解决方案使用keyframes和 CSS 中的一个小技巧/幻觉来仅在两个span -s 上创建无限旋转动画。 After every animation iteration , the text of each span changes using JS.每次动画迭代后,每个跨度的文本都使用 JS 更改。 The changed text depends on the data-texts attribute in your HTML.更改的文本取决于 HTML 中的data-texts属性。 In your ReactJS code, you can simply feed all the texts you want to spin inside these data-texts attributes.在你的 ReactJS 代码中,你可以简单地在这些data-texts属性中输入你想要旋转的所有data-texts

 const spinnerTexts = document.querySelectorAll('[class^="spinner__text--"]') const texts = spinnerTexts[0].dataset.texts.split(',') const textPositions = [0, 1] function initializeSpinnerTexts() { spinnerTexts.forEach((spinnerText, index) => { // Initialize the spinner texts' text spinnerText.innerText = texts[textPositions[index]] // Change text after every animation iteration spinnerText.addEventListener('animationiteration', e => { e.target.innerText = texts[++textPositions[index] % texts.length] }) }) } window.onload = initializeSpinnerTexts
 * { margin: 0; padding: 0; } .spinner { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); overflow: hidden; } .spinner__text { position: relative; display: inline-block; /* width has to be set to be >= largest spinning text width */ width: 50px; } .spinner__text--top, .spinner__text--bottom { display: inline-block; animation: 1s ease 1.05s infinite running none; } .spinner__text--top { animation-name: spinTop; } /* Bottom text spinner has to be configured so that it is positioned right at the same position as the top one */ .spinner__text--bottom { position: absolute; top: 0; left: 0; opacity: 0; animation-name: spinBottom; } @keyframes spinTop { from { transform: translateY(0%); } to { transform: translateY(-100%); } } @keyframes spinBottom { from { opacity: 1; transform: translateY(100%); } to { opacity: 1; transform: translateY(0%); } }
 <div class="spinner"> This is a <!-- Uses two spans to create an illusion of infinite spinning --> <div class="spinner__text"> <span class="spinner__text--top" data-texts="test., bug., fail."></span> <span class="spinner__text--bottom" data-texts="text., bug., fail."></span> </div> </div>


Update更新

You can't add a delay between each animation iteration using keyframes directly.您不能直接使用keyframes在每次动画迭代之间添加延迟。 However, you can adjust the values of the keyframes and the value of animation-duration such that it looks like there's a delay in between each iteration;但是,您可以调整keyframes的值和animation-duration的值,使每次迭代之间看起来都有延迟; in actuality, you're making it so that nothing is happening during the end of each animation.实际上,您正在制作它,以便在每个动画结束时都不会发生任何事情。 Here's an example below (it's similar to the above one, but with slight adjustments to animation-duration and keyframes .下面是一个示例(它类似于上面的示例,但对animation-durationkeyframes稍作调整。

 const spinnerTexts = document.querySelectorAll('[class^="spinner__text--"]') const texts = spinnerTexts[0].dataset.texts.split(',') const textPositions = [0, 1] function initializeSpinnerTexts() { spinnerTexts.forEach((spinnerText, index) => { // Initialize the spinner texts' text spinnerText.innerText = texts[textPositions[index]] // Change text after every animation iteration spinnerText.addEventListener('animationiteration', e => { e.target.innerText = texts[++textPositions[index] % texts.length] }) }) } window.onload = initializeSpinnerTexts
 * { margin: 0; padding: 0; } .spinner { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); overflow: hidden; } .spinner__text { position: relative; display: inline-block; width: 50px; } .spinner__text--top, .spinner__text--bottom { display: inline-block; /* Changed animation duration */ animation: 5s ease 2s infinite running none; } .spinner__text--top { animation-name: spinTop; } .spinner__text--bottom { position: absolute; top: 0; left: 0; opacity: 0; animation-name: spinBottom; } @keyframes spinTop { 0% { transform: translateY(0%); } /* Spin finishes after 20% of animation duration (1s) */ 20% { transform: translateY(-100%); } /* Nothing from 20% until 100% of animation duration (4s) */ /* This makes it looks like there's a delay between each animation */ 100% { transform: translateY(-100%); } } @keyframes spinBottom { /* Similar to spinTop's logic */ 0% { opacity: 1; transform: translateY(100%); } 20% { opacity: 1; transform: translateY(0%); } 100% { opacity: 1; transform: translateY(0%); } }
 <div class="spinner"> This is a <!-- Uses two spans to create an illusion of infinite spinning --> <div class="spinner__text"> <span class="spinner__text--top" data-texts="test., bug., fail."></span> <span class="spinner__text--bottom" data-texts="text., bug., fail."></span> </div> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM