【问题标题】:Javascript animations in timed sequence定时序列中的Javascript动画
【发布时间】:2018-03-06 20:40:31
【问题描述】:

我正在使用 Javascript 处理几个 CSS 类。我的剧本是按时间顺序播放的,它们一起播放动画。我觉得我很接近,但我被卡住了,有什么见解吗?

基本上,我需要第 1 步和第 2 步同时进行,持续一秒钟,第 3 步在第 1 步和第 2 步之后持续一秒钟,第 4 步和第 5 步在在步骤 1、2、3 和 4....等之后的持续时间相同的时间为一秒。在第 6 步结束时,重置计时器并重复。

我有一个 SVG,它由一堆线条组成。其中一些线必须在序列中的某个时间“打开”,一些必须变大,所以我正在切换它们的类,但只在那个特定时间,否则它们会关闭。

这就是我的代码的样子(简单的 SVG 只是一个演示模型)。它将手动向元素添加类,但不会重置其计时器并无限重复,因为我无法弄清楚如何在添加类后清除它们:

<!DOCTYPE html>
<html>
<head>
    <style>
      #line1, #line2, #line3, #line4, #line5, #line6 {
          visiblity: hidden;
      }

      .showElement {
          visibility: visible !important;
      }   

      .growElement {
          transform: scale(1.5) perspective(1px);
      }
    </style>
</head>

<body>

<svg height="210" width="500">
  <line id="line1" class="first" x1="0" y1="0" x2="200" y2="200" style="stroke:red;stroke-width:2" />
  <line id="line2" class="first" x1="0" y1="0" x2="200" y2="300" style="stroke:orange;stroke-width:2" />
  <line id="line3" class="second" x1="0" y1="0" x2="200" y2="400" style="stroke:yellow;stroke-width:2" />
  <line id="line4" class="third" x1="0" y1="0" x2="200" y2="500" style="stroke:green;stroke-width:2" />
  <line id="line5" class="fourth" x1="0" y1="0" x2="200" y2="600" style="stroke:blue;stroke-width:2" />
  <line id="line6" class="fifth" x1="0" y1="0" x2="200" y2="700" style="stroke:purple;stroke-width:2" />
  <line id="line7" class="sixth" x1="0" y1="0" x2="200" y2="800" style="stroke:pink;stroke-width:2" />
</svg>

<script>
        document.addEventListener('DOMContentLoaded', function() {

            setInterval(function() {
                // create array of all the elements with the class 'first', loop over each one
                // in this case, ['
                var firstClass = document.getElementsByClassName("first");
                console.log(firstClass[0]);
                console.log(firstClass[1]);
                setInterval(function(){
                    firstClass[0].classList.add("showElement");
                    firstClass[1].classList.add("showElement");
                }, 1000);

                var secondClass = document.getElementsByClassName("second");
                console.log(secondClass[0]);
                console.log(secondClass[1]);
                setInterval(function(){
                    secondClass[0].classList.add("showElement");
                    secondClass[1].classList.add("showElement");
                }, 2000);

                var thirdClass = document.getElementsByClassName("third");
                console.log(thirdClass[0]);
                setInterval(function(){
                    thirdClass[0].classList.add("showElement");
                }, 3000);

                var fourthClass = document.getElementsByClassName("fourth");
                console.log(fourthClass[0]);
                setInterval(function(){
                    fourthClass[0].classList.add("showElement");
                }, 4000);
            }, 4000);
     });
</script>

</body>
</html>

我还需要弄清楚如何一次添加多个类,只需几个步骤。比如 element .first, .second 和 .third 我想突然出现所以我给他们.showElement,但是 element .third 我也想加 .growElement。我该怎么做?

这是我的 Javascript 代码,它不能同时接受多个东西。它使用一个计数器,所以不像以前那样粗糙。它查看列表中的每个项目并应用一种样式:

<script>
document.addEventListener('DOMContentLoaded', function() {

    var connections = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth'];
    var i = 0; // index of the first item to show


    setInterval(function(){
        console.log(connections[i]);
        document.getElementsByClassName(connections[i]).classList.add("showElement");

        var counter = connections[i++];  // get the current item index and increment
        if ((i == connections.length)) {
            i = 0; // reset to first element if reach the end
        }
    }, 1000);

});

注意:我不打算使用 jQuery,只是想使用纯 JavaScript。该动画存在于一个单页网站上,没有其他带有外部 SVG 的 JavaScript,因此它必须存在于 SVG 文件中,我认为安装大型库没有多大意义。

但我正在寻找可能的更好方法来解决这个问题。有人告诉我这是“承诺”的工作。我现在正在研究 Snap.svg、Q、When、WinJS 和 RSVP.js 库,如果您认为它会更好(甚至 jQuery,如果它真的更容易的话),我会欢迎您提出建议。

【问题讨论】:

  • 只是说明您希望它如何运行。在一秒钟内将 showElement 添加到 className 为 1 的所有元素。您是否希望该 showElement 持续整整 6 秒,然后将其从所有内容中删除并重复...或者仅在最初的 1 秒内持续,然后将其删除。
  • 是的,正如您所描述的那样。它可以持续整整 6 秒……这是迄今为止我让它工作的唯一方法。理想情况下,它只会持续 1 秒,然后被删除。
  • 所以理想情况下,在这样的时间图中,你能告诉我它应该如何运行1: 1 2: 23: 3 经过几秒钟:显示元素,即在什么时候显示什么元素及时。
  • 在我看来这在 SMIL 中会容易得多,您可以在其中链接动画

标签: javascript css svg snap.svg


【解决方案1】:

这是一个更简洁的版本,它以 1 秒的间隔执行动画,让您更明显地控制每一帧上发生的事情。

要添加多个类,您可以一次添加您喜欢的任何内容,例如:classList.Add('showElement', 'growElement')(删除也是如此。See examples

动画将通过在最后一帧中将帧设置回 0 来重复循环(0 是因为帧计数器在 switch 语句之后递增)。然后在第一帧确保清除最后一帧的样式。

<html>
<head>
    <style>
      #line1, #line2, #line3, #line4, #line5, #line6, #line7 {
        visibility: hidden;
        transform: scale(1) perspective(1);
        transition: .5s transform;
      }

      .showElement {
          visibility: visible !important;
      }   

      .growElement {
          transform: scale(3.5) perspective(1px);
      }
    </style>
</head>

<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.2/plugins/CSSPlugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.2/easing/EasePack.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.2/TweenLite.min.js"></script>
  
<svg height="210" width="500">
  <line id="line1" class="first" x1="0" y1="0" x2="200" y2="200" style="stroke:red;stroke-width:2" />
  <line id="line2" class="first" x1="0" y1="0" x2="200" y2="300" style="stroke:orange;stroke-width:2" />
  <line id="line3" class="second" x1="0" y1="0" x2="200" y2="400" style="stroke:yellow;stroke-width:2" />
  <line id="line4" class="third" x1="0" y1="0" x2="200" y2="500" style="stroke:green;stroke-width:2" />
  <line id="line5" class="fourth" x1="0" y1="0" x2="200" y2="600" style="stroke:blue;stroke-width:2" />
  <line id="line6" class="fifth" x1="0" y1="0" x2="200" y2="700" style="stroke:purple;stroke-width:2" />
  <line id="line7" class="sixth" x1="0" y1="0" x2="200" y2="800" style="stroke:pink;stroke-width:2" />
</svg>

<script>
                
var frame = 1;

// create array of all the elements with the class 'first', loop over each one
// in this case, ['
var firstClass = document.getElementsByClassName("first");
var secondClass = document.getElementsByClassName("second");
var thirdClass = document.getElementsByClassName("third");
var fourthClass = document.getElementsByClassName("fourth");
var fifthClass = document.getElementsByClassName("fifth");
var sixthClass = document.getElementsByClassName("sixth");
var seventhClass = document.getElementsByClassName("seventh");

function hideUnusedClasses(p_classesArray) {
  p_classesArray.forEach(function(array, index){
    for(var i=0;i<array.length;++i) {
      array[i].classList.remove('showElement', 'growElement');
    }
  });
}

var interval = setInterval(function(){
  //console.log('Run every 1 second');
  switch(frame) {
    case 1:
      //console.log('frame', frame);
      hideUnusedClasses([sixthClass]);
      for(var i=0;i<firstClass.length;++i) { 
        firstClass[i].classList.add('showElement');
      }
      break;
    case 2:
      //console.log('frame', frame);
      //console.log('Delete 1 class');
      hideUnusedClasses([firstClass]); 
      for(var i=0;i<secondClass.length;++i) {
        secondClass[i].classList.add('showElement');
      }
      break;
    case 3:
      //console.log('frame', frame);
      //console.log('Delete 2 class');
      hideUnusedClasses([secondClass]);
      for(var i=0;i<thirdClass.length;++i) {
        thirdClass[i].classList.add('showElement', 'growElement');
      }
      break;
    case 4:
      //console.log('frame', frame);
      hideUnusedClasses([thirdClass]);
      //console.log('Delete 3 class');
      for(var i=0;i<fourthClass.length;++i) {
        fourthClass[i].classList.add('showElement');
      }
      break;
    case 5:
      //console.log('frame', frame);
      hideUnusedClasses([fourthClass]);
      for(var i=0;i<fifthClass.length;++i) {
        fifthClass[i].classList.add('showElement');
      }
      break;
    case 6:
      //console.log('frame', frame);
      hideUnusedClasses([fifthClass]);
      for(var i=0;i<sixthClass.length;++i) {
        sixthClass[i].classList.add('showElement');
      }
      frame = 0;
      break;  
    default:
      //console.log('all done');
      //clearInterval(interval);
  }
  ++frame;
}, 1000);
</script>

</body>
</html>

【讨论】:

  • 这正是我想要完成的。您知道如何将其置于无限循环中吗?这样最后一堂课动画完后,会重复到第一堂课?
  • 更新了代码以使其循环 - 只需在动画结束时重置帧。
【解决方案2】:
var connections = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth'];

function showElements(i,duration){
    var elements = document.getElementsByClassName(connections[i]); 
    elements.map((e) =>  e.classList.add('showElement'))
    setTimeout(()=>{
        //remove the .showElement after duration to display has elapsed
        elements.map((e)=> e.classList.remove('showElement'))
        //recursively calls the next animation to be played, resets at 6
        showElements((i+1)%6,duration)
    },duration)        
}

不确定这是否是您想要的方式,但它会在持续时间内将 showElement 添加到每个,然后将其删除。

showElements(0,1000)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-15
    • 2019-03-16
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 2022-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多