【问题标题】:CSS3 Keyframe Animation issue with "timelines"“时间线”的 CSS3 关键帧动画问题
【发布时间】:2016-11-09 02:45:14
【问题描述】:

在下面的示例中,我有 3 个 div,它们需要使用 CSS3 Keyframe Animation 进行动画处理,规则如下(当我在下面的文本中提到隐藏/显示时,实际上在 CSS 中使用 opacity 0.1/1):

A) 页面加载时

  • ladyDefault 显示
  • ladyCorrect 已隐藏
  • ladyWrong 已隐藏

B) 当用户点击 btnCorrect 时

  • ladyDefault 已隐藏
  • ladyCorrect 已显示
  • ladyWrong 已隐藏

C) 当用户点击 btnWrong 时

  • ladyDefault 已隐藏
  • ladyCorrect 已隐藏
  • 显示ladyWrong

目前:

  • 序列案例 A) 和 B) 工作正常。

  • 序列案例 A) 和 C) 工作正常。

但我无法解决以下情况:

  • 顺序情况 A) 和 B) 和 C) 不起作用(ladyWrong 未显示)。

  • 顺序情况 A) 和 C) 和 B) 不起作用(ladyCorrect 未显示)。

我想知道如何仅使用 CSS 3 来修复它。

仅使用 Google Chrome 测试以下示例。

var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');

btnCorrect.addEventListener('click', function(event) {
    ladyDefault.classList.add('hideLadyDefault');
    ladyWrong.classList.add('hideLadyWrong');
    ladyCorrect.classList.add('showLadyCorrect');
});
btnWrong.addEventListener('click', function(event) {
    ladyDefault.classList.add('hideLadyDefault');
    ladyCorrect.classList.add('hideLadyCorrect');
    ladyWrong.classList.add('showLadyWrong');
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
    width: 100px;
    height: 150px;
    display: inline-block;
    margin: 5px;
}

#ladyDefault {
    background-color: blue;
}

#ladyCorrect {
    background-color: green;
    opacity: 0.1;
}

#ladyWrong {
    background-color: red;
    opacity: 0.1;
}

#btnCorrect,
#btnWrong {
    height: 50px;
    width: 100px;
    display: inline-block;
    margin: 5px;
}

#btnCorrect {
    background-color: lime;
}

#btnWrong {
    background-color: darkred;
}
/*
--------------------------- lady default
*/
@keyframes hideLadyDefault {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0.1;
    }
}

.hideLadyDefault {
    animation-name: hideLadyDefault;
    animation-duration: 0;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: forwards;
    animation-delay: 0;
}
/*
--------------------------- lady correct
*/
@keyframes showLadyCorrect {
    0% {
        opacity: 0.1;
    }
    100% {
        opacity: 1;
    }
}

.showLadyCorrect {
    animation-name: showLadyCorrect;
    animation-duration: 1s;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: forwards;
    animation-delay: 0;
}

@keyframes hideLadyCorrect {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0.1;
    }
}

.hideLadyCorrect {
    animation-name: hideLadyCorrect;
    animation-duration: 0;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: both
    animation-delay: 0;
}
/*
--------------------------- lady wrong
*/
@keyframes showLadyWrong {
    0% {
        opacity: 0.1;
    }
    100% {
        opacity: 1;
    }
}

.showLadyWrong {
    animation-name: showLadyWrong;
    animation-duration: 1s;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: forwards;
    animation-delay: 0;
}

@keyframes hideLadyWrong {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0.1;
    }
}

.hideLadyWrong {
    animation-name: hideLadyWrong;
    animation-duration: 0;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: both;
    animation-delay: 0;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>

<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>

【问题讨论】:

    标签: javascript html css css-animations


    【解决方案1】:

    原答案:

    在添加新类之前,您还需要删除以前的类。当您在添加新类之前不删除另一个类时,他们每个人都会尝试在同一个元素上设置一个animation,就像 CSS 一样,选择器(类)稍后在 CSS 中定义赢了。

    var btnCorrect = document.getElementById('btnCorrect');
    var btnWrong = document.getElementById('btnWrong');
    var ladyDefault = document.getElementById('ladyDefault');
    var ladyCorrect = document.getElementById('ladyCorrect');
    var ladyWrong = document.getElementById('ladyWrong');
    
    btnCorrect.addEventListener('click', function(event) {
      ladyDefault.classList.add('hideLadyDefault');
      ladyWrong.classList.remove('showLadyWrong');
      ladyWrong.classList.add('hideLadyWrong');
      ladyCorrect.classList.remove('hideLadyCorrect');
      ladyCorrect.classList.add('showLadyCorrect');
    });
    btnWrong.addEventListener('click', function(event) {
      ladyDefault.classList.add('hideLadyDefault');
      ladyCorrect.classList.remove('showLadyCorrect');
      ladyCorrect.classList.add('hideLadyCorrect');
      ladyWrong.classList.remove('hideLadyWrong');
      ladyWrong.classList.add('showLadyWrong');
    });
    #ladyDefault,
    #ladyCorrect,
    #ladyWrong {
      width: 100px;
      height: 150px;
      display: inline-block;
      margin: 5px;
    }
    #ladyDefault {
      background-color: blue;
    }
    #ladyCorrect {
      background-color: green;
      opacity: 0.1;
    }
    #ladyWrong {
      background-color: red;
      opacity: 0.1;
    }
    #btnCorrect,
    #btnWrong {
      height: 50px;
      width: 100px;
      display: inline-block;
      margin: 5px;
    }
    #btnCorrect {
      background-color: lime;
    }
    #btnWrong {
      background-color: darkred;
    }
    /*
    --------------------------- lady default
    */
    
    @keyframes hideLadyDefault {
      0% {
        opacity: 1;
      }
      100% {
        opacity: 0.1;
      }
    }
    .hideLadyDefault {
      animation-name: hideLadyDefault;
      animation-duration: 0;
      animation-iteration-count: 1;
      animation-direction: normal;
      animation-fill-mode: forwards;
      animation-delay: 0;
    }
    /*
    --------------------------- lady correct
    */
    
    @keyframes showLadyCorrect {
      0% {
        opacity: 0.1;
      }
      100% {
        opacity: 1;
      }
    }
    .showLadyCorrect {
      animation-name: showLadyCorrect;
      animation-duration: 1s;
      animation-iteration-count: 1;
      animation-direction: normal;
      animation-fill-mode: forwards;
      animation-delay: 0;
    }
    @keyframes hideLadyCorrect {
      0% {
        opacity: 1;
      }
      100% {
        opacity: 0.1;
      }
    }
    .hideLadyCorrect {
      animation-name: hideLadyCorrect;
      animation-duration: 0;
      animation-iteration-count: 1;
      animation-direction: normal;
      animation-fill-mode: both animation-delay: 0;
    }
    /*
    --------------------------- lady wrong
    */
    
    @keyframes showLadyWrong {
      0% {
        opacity: 0.1;
      }
      100% {
        opacity: 1;
      }
    }
    .showLadyWrong {
      animation-name: showLadyWrong;
      animation-duration: 1s;
      animation-iteration-count: 1;
      animation-direction: normal;
      animation-fill-mode: forwards;
      animation-delay: 0;
    }
    @keyframes hideLadyWrong {
      0% {
        opacity: 1;
      }
      100% {
        opacity: 0.1;
      }
    }
    .hideLadyWrong {
      animation-name: hideLadyWrong;
      animation-duration: 0;
      animation-iteration-count: 1;
      animation-direction: normal;
      animation-fill-mode: both;
      animation-delay: 0;
    }
    <div id="ladyDefault">ladyDefault</div>
    <div id="ladyCorrect">ladyCorrect</div>
    <div id="ladyWrong">ladyWrong</div>
    
    <div id="btnCorrect">btnCorrect</div>
    <div id="btnWrong">btnWrong</div>

    只有一个关键帧规则的解决方案:

    您也可以使用单个@keyframes 规则而不是使用多个规则来实现相同的效果。所需要的只是将animation-direction 设置为reverse 以用于隐藏。但是旧的类仍然必须删除,因为一旦在元素上设置了动画,UA 就会记住它的执行,如 this answer of mine 中所述。

    var btnCorrect = document.getElementById('btnCorrect');
    var btnWrong = document.getElementById('btnWrong');
    var ladyDefault = document.getElementById('ladyDefault');
    var ladyCorrect = document.getElementById('ladyCorrect');
    var ladyWrong = document.getElementById('ladyWrong');
    
    btnCorrect.addEventListener('click', function(event) {
      ladyDefault.classList.add('hideLadyDefault');
      ladyWrong.classList.remove('showLadyWrong');
      ladyWrong.classList.add('hideLadyWrong');
      ladyCorrect.classList.remove('hideLadyCorrect');
      ladyCorrect.classList.add('showLadyCorrect');
    });
    btnWrong.addEventListener('click', function(event) {
      ladyDefault.classList.add('hideLadyDefault');
      ladyCorrect.classList.remove('showLadyCorrect');
      ladyCorrect.classList.add('hideLadyCorrect');
      ladyWrong.classList.remove('hideLadyWrong');
      ladyWrong.classList.add('showLadyWrong');
    });
    #ladyDefault,
    #ladyCorrect,
    #ladyWrong {
      width: 100px;
      height: 150px;
      display: inline-block;
      margin: 5px;
    }
    #ladyDefault {
      background-color: blue;
    }
    #ladyCorrect {
      background-color: green;
      opacity: 0.1;
    }
    #ladyWrong {
      background-color: red;
      opacity: 0.1;
    }
    #btnCorrect,
    #btnWrong {
      height: 50px;
      width: 100px;
      display: inline-block;
      margin: 5px;
    }
    #btnCorrect {
      background-color: lime;
    }
    #btnWrong {
      background-color: darkred;
    }
    /*
    --------------------------- lady default
    */
    
    .hideLadyDefault {
      animation-name: show;
      animation-duration: 0;
      animation-iteration-count: 1;
      animation-direction: reverse;
      animation-fill-mode: forwards;
      animation-delay: 0;
    }
    /*
    --------------------------- lady correct
    */
    
    @keyframes show {
      0% {
        opacity: 0.1;
      }
      100% {
        opacity: 1;
      }
    }
    .showLadyCorrect {
      animation-name: show;
      animation-duration: 1s;
      animation-iteration-count: 1;
      animation-direction: normal;
      animation-fill-mode: forwards;
      animation-delay: 0;
    }
    .hideLadyCorrect {
      animation-direction: reverse;
    }
    /*
    --------------------------- lady wrong
    */
    
    .showLadyWrong {
      animation-name: show;
      animation-duration: 1s;
      animation-iteration-count: 1;
      animation-direction: normal;
      animation-fill-mode: forwards;
      animation-delay: 0;
    }
    .hideLadyWrong {
      animation-direction: reverse;
    }
    <div id="ladyDefault">ladyDefault</div>
    <div id="ladyCorrect">ladyCorrect</div>
    <div id="ladyWrong">ladyWrong</div>
    
    <div id="btnCorrect">btnCorrect</div>
    <div id="btnWrong">btnWrong</div>

    有过渡的解决方案:(可能更合适)

    如果可以的话,更好的选择是使用transition 而不是animation。在这里,您可以通过内联样式属性设置opacity,并让transition 属性处理其余部分。与动画不同,过渡默认情况下可以执行反向状态。 (如果只是将不透明度从 0.1 简单更改为 1,这是最好的选择,如果是复杂的多步更改,则过渡超出范围。)

    var btnCorrect = document.getElementById('btnCorrect');
    var btnWrong = document.getElementById('btnWrong');
    var ladyDefault = document.getElementById('ladyDefault');
    var ladyCorrect = document.getElementById('ladyCorrect');
    var ladyWrong = document.getElementById('ladyWrong');
    
    btnCorrect.addEventListener('click', function(event) {
      ladyDefault.style["opacity"] = "0.1";
      ladyWrong.style["opacity"] = "0.1";
      ladyCorrect.style["opacity"] = "1";
    });
    btnWrong.addEventListener('click', function(event) {
      ladyDefault.style["opacity"] = "0.1";
      ladyCorrect.style["opacity"] = "0.1";
      ladyWrong.style["opacity"] = "1";
    });
    #ladyDefault,
    #ladyCorrect,
    #ladyWrong {
      width: 100px;
      height: 150px;
      display: inline-block;
      margin: 5px;
    }
    #ladyDefault {
      background-color: blue;
      transition: all 1s ease;
    }
    #ladyCorrect {
      background-color: green;
      opacity: 0.1;
      transition: all 1s ease;
    }
    #ladyWrong {
      background-color: red;
      opacity: 0.1;
      transition: all 1s ease;
    }
    #btnCorrect,
    #btnWrong {
      height: 50px;
      width: 100px;
      display: inline-block;
      margin: 5px;
    }
    #btnCorrect {
      background-color: lime;
    }
    #btnWrong {
      background-color: darkred;
    }
    <div id="ladyDefault">ladyDefault</div>
    <div id="ladyCorrect">ladyCorrect</div>
    <div id="ladyWrong">ladyWrong</div>
    
    <div id="btnCorrect">btnCorrect</div>
    <div id="btnWrong">btnWrong</div>

    【讨论】:

    • 非常感谢您的回答,请问...您认为实际上可以“倒带”动画而不是删除课程吗?
    • @GibboK:是的,您实际上可以通过使用animation-direction 来使用单个关键帧本身来做到这一点。稍后会更新答案。
    • @GibboK:但是您仍然需要指定方向何时应更改为反向,因此我可以想到两个选项-(1)通过样式属性设置/取消设置animation-direction通过JS(2)保留remove类模型(但至少关键帧只是一个)。你更喜欢哪一个?我可能会在答案中发布两个版本。
    • @GibboK:对不起,当我给你这个评论时,我一定是处于一种困惑的状态。一旦动画被执行,我们就无法执行反向操作,除非我们通过删除类(或)通过更改 animation 内联样式来删除 animation。这是一个可能会给你一些额外信息的线程 - stackoverflow.com/questions/33347992/…
    • @GibboK:另外,最好使用transition 而不是animation。 (这在另一个线程中也提到了,但我在这里也添加了一个演示。)
    【解决方案2】:

    您正确添加了所有类,但您没有稍后删除添加的类,这就是问题所在。将您的听众更改为

    btnCorrect.addEventListener('click', function(event) {
        ladyDefault.classList.add('hideLadyDefault');
        ladyWrong.classList.add('hideLadyWrong');
        ladyCorrect.classList.add('showLadyCorrect');
        ladyCorrect.classList.remove('hideLadyCorrect'); //added
    });
    btnWrong.addEventListener('click', function(event) {
        ladyDefault.classList.add('hideLadyDefault');
        ladyCorrect.classList.add('hideLadyCorrect');
        ladyWrong.classList.add('showLadyWrong');
        ladyWrong.classList.remove('hideLadyWrong'); //added
    });
    

    var btnCorrect = document.getElementById('btnCorrect');
    var btnWrong = document.getElementById('btnWrong');
    var ladyDefault = document.getElementById('ladyDefault');
    var ladyCorrect = document.getElementById('ladyCorrect');
    var ladyWrong = document.getElementById('ladyWrong');
    
    btnCorrect.addEventListener('click', function(event) {
        ladyDefault.classList.add('hideLadyDefault');
        ladyWrong.classList.add('hideLadyWrong');
        ladyCorrect.classList.add('showLadyCorrect');
        ladyCorrect.classList.remove('hideLadyCorrect');
    });
    btnWrong.addEventListener('click', function(event) {
        ladyDefault.classList.add('hideLadyDefault');
        ladyCorrect.classList.add('hideLadyCorrect');
        ladyWrong.classList.add('showLadyWrong');
        ladyWrong.classList.remove('hideLadyWrong');
    });
    #ladyDefault,
    #ladyCorrect,
    #ladyWrong {
        width: 100px;
        height: 150px;
        display: inline-block;
        margin: 5px;
    }
    
    #ladyDefault {
        background-color: blue;
    }
    
    #ladyCorrect {
        background-color: green;
        opacity: 0.1;
    }
    
    #ladyWrong {
        background-color: red;
        opacity: 0.1;
    }
    
    #btnCorrect,
    #btnWrong {
        height: 50px;
        width: 100px;
        display: inline-block;
        margin: 5px;
    }
    
    #btnCorrect {
        background-color: lime;
    }
    
    #btnWrong {
        background-color: darkred;
    }
    /*
    --------------------------- lady default
    */
    @keyframes hideLadyDefault {
        0% {
            opacity: 1;
        }
        100% {
            opacity: 0.1;
        }
    }
    
    .hideLadyDefault {
        animation-name: hideLadyDefault;
        animation-duration: 0;
        animation-iteration-count: 1;
        animation-direction: normal;
        animation-fill-mode: forwards;
        animation-delay: 0;
    }
    /*
    --------------------------- lady correct
    */
    @keyframes showLadyCorrect {
        0% {
            opacity: 0.1;
        }
        100% {
            opacity: 1;
        }
    }
    
    .showLadyCorrect {
        animation-name: showLadyCorrect;
        animation-duration: 1s;
        animation-iteration-count: 1;
        animation-direction: normal;
        animation-fill-mode: forwards;
        animation-delay: 0;
    }
    
    @keyframes hideLadyCorrect {
        0% {
            opacity: 1;
        }
        100% {
            opacity: 0.1;
        }
    }
    
    .hideLadyCorrect {
        animation-name: hideLadyCorrect;
        animation-duration: 0;
        animation-iteration-count: 1;
        animation-direction: normal;
        animation-fill-mode: both
        animation-delay: 0;
    }
    /*
    --------------------------- lady wrong
    */
    @keyframes showLadyWrong {
        0% {
            opacity: 0.1;
        }
        100% {
            opacity: 1;
        }
    }
    
    .showLadyWrong {
        animation-name: showLadyWrong;
        animation-duration: 1s;
        animation-iteration-count: 1;
        animation-direction: normal;
        animation-fill-mode: forwards;
        animation-delay: 0;
    }
    
    @keyframes hideLadyWrong {
        0% {
            opacity: 1;
        }
        100% {
            opacity: 0.1;
        }
    }
    
    .hideLadyWrong {
        animation-name: hideLadyWrong;
        animation-duration: 0;
        animation-iteration-count: 1;
        animation-direction: normal;
        animation-fill-mode: both;
        animation-delay: 0;
    }
    <div id="ladyDefault">ladyDefault</div>
    <div id="ladyCorrect">ladyCorrect</div>
    <div id="ladyWrong">ladyWrong</div>
    
    <div id="btnCorrect">btnCorrect</div>
    <div id="btnWrong">btnWrong</div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-19
      • 2012-12-22
      • 1970-01-01
      • 2015-07-03
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2020-12-23
      相关资源
      最近更新 更多