首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无限SVG动画在悬停状态下平滑地恢复初始状态

无限SVG动画在悬停状态下平滑地恢复初始状态
EN

Stack Overflow用户
提问于 2020-11-26 12:02:58
回答 2查看 65关注 0票数 0

我希望我的无限svg动画暂停它的初始或最终状态时,我悬停它。我尝试使用JS删除类,或者在CSS中在悬停或设置animation-iteration-count: unset;时设置animation: none;,但在每种情况下,转换都是突然的。我想要顺滑的。下面是代码: HTML

代码语言:javascript
复制
    <div class="button">
        <svg version="1.1" id="sound--icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
        viewBox="0 0 100 100"   >
          <rect class="rect-1 rect-anim" x="10" fill="currentColor"></rect>
          <rect class="rect-2 rect-anim" x="30" fill="currentColor"></rect>
          <rect class="rect-3 rect-anim" x="50" fill="currentColor"></rect> 
          <rect class="rect-4 rect-anim" x="70" fill="currentColor"></rect>
      </svg>
    </div>

CSS

代码语言:javascript
复制
#sound--icon .rect-anim{
    animation-name: sound-icon-anim;
    animation-duration: .8s;
    animation-timing-function: cubic-bezier(.97,0,0,1);
    animation-iteration-count: infinite;
}

/*  #sound--icon:hover .rect-anim{
    animation-iteration-count: unset;
} 
 */

#sound--icon .rect-1{
    animation-delay: .1s;
}

#sound--icon .rect-2{
    animation-delay: .3s;
}

#sound--icon .rect-3{
    animation-delay: .5s;
}

#sound--icon .rect-4{
    animation-delay: .7s;
}

@keyframes sound-icon-anim{
    0%{
        height: 30%;
    }
    10%{
        height: 70%;
    }
    20%{
        height: 50%;
    }
    50%{
        height: 80%;
    }
    60%{
        height: 100%;
    }
    70%{
        height: 70%;
    }
    100%{
        height: 30%;
    }
}

我最终要做的是:

  • 动画正在运行
  • 当div被悬停/动画暂停时,高度平稳地达到50%。
  • 当点击div /暂停动画时,高度平稳地下降到30%。
  • 当div再次悬停/动画仍然暂停时,高度平稳地达到50%。
  • 再次单击div时动画重新运行(因此从50%开始,而不是在0%的动画状态下从30%开始运行)

在纯CSS中,这似乎是可能的吗?

EN

回答 2

Stack Overflow用户

发布于 2020-11-26 16:12:52

我不认为你能在纯CSS中做到这一点。有了Web动画API,这是可能的,但在目前的实现状态下,只有一部分是现实的。

您可以实现的是在迭代周期结束时停止动画。在一个不是循环结束的点停止将需要实现AnimationTimeline。但Chrome目前还缺少这款手机。

代码语言:javascript
复制
document.querySelectorAll('.button').forEach(button => {
    //.getAnimations() returns an array
    const animations = [...button.querySelectorAll('.rect-anim')]
        .map(r => r.getAnimations())
        .flat();

    button.addEventListener('mouseenter', () => {
        for (let animation of animations) {
            const iterations = animation.effect.getComputedTiming()
                .currentIteration + 1;
            animation.effect.updateTiming({iterations})
        }
    });

    button.addEventListener('mouseleave', () => {
        for (let animation of animations) {
            animation.effect.updateTiming({iterations: Infinity});
        }
  });
});
代码语言:javascript
复制
.button {
  margin: 20px;
  width: 100px;
}

#sound--icon .rect-anim{
    animation-name: sound-icon-anim;
    animation-duration: .8s;
    animation-timing-function: cubic-bezier(.97,0,0,1);
    animation-iteration-count: infinite;
}

#sound--icon .rect-1{
    animation-delay: .1s;
}

#sound--icon .rect-2{
    animation-delay: .3s;
}

#sound--icon .rect-3{
    animation-delay: .5s;
}

#sound--icon .rect-4{
    animation-delay: .7s;
}

@keyframes sound-icon-anim{
    0%{
        height: 30%;
    }
    10%{
        height: 70%;
    }
    20%{
        height: 50%;
    }
    50%{
        height: 80%;
    }
    60%{
        height: 100%;
    }
    70%{
        height: 70%;
    }
    100%{
        height: 30%;
    }
}
代码语言:javascript
复制
<div id="this-button" class="button">
    <svg version="1.1" id="sound--icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
    viewBox="0 0 100 100"   >
      <rect class="rect-1 rect-anim" x="10" y="40" width="20" height="20" fill="currentColor"></rect>
      <rect class="rect-2 rect-anim" x="30" y="40" width="20" height="20" fill="currentColor"></rect>
      <rect class="rect-3 rect-anim" x="50" y="40" width="20" height="20" fill="currentColor"></rect> 
      <rect class="rect-4 rect-anim" x="70" y="40" width="20" height="20" fill="currentColor"></rect>
  </svg>
</div>

票数 0
EN

Stack Overflow用户

发布于 2020-11-26 17:30:33

谢谢,伙计,我学到了一些东西。最后,对于JS的结果,我做了一些非常令人满意的事情。在使用getComputedStyle时,我计算了矩形的高度,并将其更改为我希望添加的转换。我认为可以优化代码,特别是删除定义动画的CSS类的setTimeout部件。如果它不在那里,它就会破坏第四个矩形。

代码语言:javascript
复制
const svg = document.querySelector('#sound__icon')
const btn = document.querySelector('.mute')
const rects = svg.children
let mute = false

function muting(){
    if(!mute){
        mute = true
      for(let rect of rects){
            rect.style.height = '30%'
      }
    }
    else{
        mute = false
        audioAnimActivate()
    }
}

function audioAnimActivate(){
    for(let rect of rects){
        rect.classList.add('rect-anim')
    }
    svg.classList.add('sound__icon--on')
}

function audioAnimFreeze(){
    for(let rect of rects){
        let rectHeight = window.getComputedStyle(rect).height
        rect.style.height = rectHeight
        rect.classList.remove('rect-anim')
        rect.style.transition = 'height .5s ease'
        rect.style.height = '50%'
    }
    //? How to code this better ???
    setTimeout(() => svg.classList.remove('sound__icon--on'), 16)
}

btn.addEventListener('click', muting)
btn.addEventListener('mouseenter', () => {
    if(mute){
        rects[0].style.height = '60%'
        rects[1].style.height = '20%'
        rects[2].style.height = '40%'
        rects[3].style.height = '80%'
    }
    else{
        audioAnimFreeze()
    }
    
})
btn.addEventListener('mouseleave', () => {
    if(!mute){
        audioAnimActivate()
    }
    else{
        for(let rect of rects){
            rect.style.height = '30%'
        }
    }
}) 
代码语言:javascript
复制
.mute{
    width: 25vw;
    height: 25vw;
    border: none;
    display: flex;
    justify-content: center;
    align-items: center;
    background: none;
}

.rect-1, .rect-2, .rect-3, .rect-4{
    width: 10%;
    height: 30%;
}

.sound__icon--on .rect-anim{
    animation-name: sound-icon-anim;
    animation-duration: 1s;
    animation-timing-function: cubic-bezier(.97,0,0,1);
    animation-iteration-count: infinite;
}

.sound__icon--on .rect-1{
    animation-delay: .1s;
}

.sound__icon--on .rect-2{
    animation-delay: .3s;
}

.sound__icon--on .rect-3{
    animation-delay: .5s;
}

.sound__icon--on .rect-4{
    animation-delay: .7s;
}

@keyframes sound-icon-anim{
    0%{
        height: 30%;
    }
    10%{
        height: 70%;
    }
    20%{
        height: 50%;
    }
    50%{
        height: 80%;
    }
    60%{
        height: 100%;
    }
    70%{
        height: 70%;
    }
    100%{
        height: 30%;
    }
}
代码语言:javascript
复制
    <div class="mute">
        <svg version="1.1" id="sound__icon" class="sound__icon--on"xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
        viewBox="0 0 100 100"   >
          <rect class="rect-1 rect-anim" x="15" fill="currentColor"></rect>
          <rect class="rect-2 rect-anim" x="35" fill="currentColor"></rect>
          <rect class="rect-3 rect-anim" x="55" fill="currentColor"></rect> 
          <rect class="rect-4 rect-anim" x="75" fill="currentColor"></rect>
      </svg>
    </div>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65021727

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档