如何一个接一个地修改多个元素 [英] How to modify multiple elements, one after the other

查看:112
本文介绍了如何一个接一个地修改多个元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个图像推子。我有它,以便它消除由 getElementById 方法选择的图像(或在这种情况下div与背景颜色),但我想知道我如何修改JavaScript用于选择所有div元素并逐个淡出的代码。



  var c = document.getElementById(one); function fade(){if(!c.style.opacity){c.style.opacity = 1; }; var interval = setInterval(fadeout,200); function fadeout(){c.style.opacity  -  = .05; if(c.style.opacity< = 0){clearInterval(interval); }; };}; fade();  

  #container {position :亲戚保证金:0自动; text-align:center;宽度:350px;身高:350px; background-color:rgb(200,200,200);}。inner {position:absolute;保证金:0自动;左:25px;上:25px;宽度:300px;身高:300px;}#one {background-color:rgb(100,100,100);}#two {background-color:rgb(0,160,230);}#three {background-color:rgb(0,255,130);}#four {background-color :rgb(255,130,255);}  

 < div id = 容器 > < div class =innerid =one>< / div> < div class =innerid =two>< / div> < div class =innerid =three>< / div> < div class =innerid =four>< / div>< / div>  



我还需要一种方法(可能使函数递归)继续从四回到一,我不会使用jQuery。

解决方案

这就是你要找的东西:



  var interval = 4000,collection = document.querySelectorAll('#container> .inner'); for(var i = 0; i< collection.length; i ++){(function(i){setTimeout(function(){collection [collection.length  -  i  -  1] .style.opacity = 0;},i * interval);})(i)}  

  #container {position:relative;保证金:0自动; text-align:center;宽度:350px;身高:350px; background-color:rgb(200,200,200);}。inner {position:absolute;保证金:0自动;左:25px;上:25px;宽度:300px;身高:300px;过渡:不透明度4s线性;}#one {background-color:rgb(100,100,100);}#two {background-color:rgb(0,160,230);}#three {background-color:rgb( 0,255,130);}#four {background-color:rgb(255,130,255);}  

 < div id =container> < div class =innerid =one>< / div> < div class =innerid =two>< / div> < div class =innerid =three>< / div> < div class =innerid =four>< / div>< / div>  



为了给它更多自然的感觉(意图,手势,活泼的印象)你需要改变 linear 放宽你在CSS中的选择:



  var interval = 4000,collection = document.querySelectorAll('#container> .inner'); for(var i = 0; i< collection.length; i ++){(function(i){setTimeout(function() {collection [collection.length  -  i  -  1] .style.opacity = 0;},i * interval);})(i)}  

  #container {position:relative;保证金:0自动; text-align:center;宽度:350px;身高:350px; background-color:rgb(200,200,200);}。inner {position:absolute;保证金:0自动;左:25px;上:25px;宽度:300px;身高:300px;过渡:不透明度4s cubic-bezier(.6,0,.3,1);} #one {background-color:rgb(100,100,100);}#two {background-color:rgb(0,160, 230);}#three {background-color:rgb(0,255,130);}#four {background-color:rgb(255,130,255);}  

 < div id =container> < div class =innerid =one>< / div> < div class =innerid =two>< / div> < div class =innerid =three>< / div> < div class =innerid =four>< / div>< / div>  



原则:每当你想要错开动画时(在一组元素上重复完全相同的动画),在一个动画结束时链接一个动画的开头以前,至少可以说是不合适的。你限制自己总是不得不等待一个动画结束才能开始下一个动画。但是,在执行脚本时,如果操作的持续时间未知,则通常需要此行为。在这里,它的持续时间相同,因此链接只是一个无用的限制。



相反,使用 setTimeout()集合,您最终可以选择在任何给定时刻动画多个元素,并对动画细节(持续时间,计时功能和交错步骤)进行更好(分离)的控制。



您的方法的另一个重大问题是您为每个元素进行了20次更改,而不是只有一次。 CSS动画可让您控制动画持续时间动画定时功能(动画动画时非常重要)和 animation-delay (此处未使用)。此外,它在浏览器上更流畅,更轻松。



我将在下面举例说明动画而不是不透明度:



< pre class =snippet-code-js lang-js prettyprint-override> //仅在js中设置交错步骤和集合//设置动画持续时间并在CSS中放宽以获得最佳结果变量= var = 63 ,// stagger step collection = document.querySelectorAll('div'); //在你的情况下,使用document.querySelectorAll('#container> .inner'); for(var i = 0; i< collection.length; i ++){(function(i){setTimeout(function(){collection [i] .style.transform ='translateX(0)';},i * interval);})(i)}

  div {background-color:#ddd; margin-top:1px;最小高度:.5rem; transform:translateX(100%); / *这里是:持续时间300毫秒,过渡*我放入立方体,因为它对交错运动有好处*它看起来很自然。对于不透明度它无关紧要*它可以是线性的,缓和的,任何东西。 * / transition:transform 1s cubic-bezier(.5,0,.1,1);} body {overflow-x:hidden; margin:0;}  

 < script src =https ://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js>< /脚本>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < div>< / div>  






初步回答,在注意到jQuery免费解决方案之前是必需的:



  //仅设置交错步骤和js中的集合//设置动画持续时间并在CSS中缓动以获得最佳结果变量= 42,//交错步骤集合= $('div'); //在你的情况下,使用$('#container> .inner'); collection.each(function(i){setTimeout(function(){collection.eq(i).css('opacity',0);} ,i * interval);}) 

  div {background-颜色:#ddd; margin-top:1px;最小高度:.5rem; / *这里是:持续时间300毫秒,过渡*我放入立方体,因为它对交错运动有好处*它看起来很自然。对于不透明度它无关紧要*它可以是线性的,缓和的,任何东西。 * / transition:opacity 300ms cubic-bezier(.4,0,.2,1);}  

 < script src =https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js>< / script>< ; DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < DIV>< / DIV>< DIV>< / DIV> < DIV>< / DIV> < div>< / div>< div>< / div>  






结束注释:这个答案甚至没有触及新的(有希望的)动画方式: Web Animations Api ,因为它仍然是实验技术。

WAA动画使用链接但提供取消动画的方法要求。它可以在所有主流浏览器中使用,并且可以在旧浏览器中与 polyfill 一起使用。

一旦Android浏览器支持它,它可能会获得巨大的普及。在此之前,动画的最佳方式是使用 CSS 动画和过渡,即使不是声明性的,也支持取消请求:您只需更改属性并自动启动来自当前状态的同一属性上的新动画,取消旧动画。唯一的CSS当前限制是它不会根据旧的持续时间计算新的持续时间,这在WAA中是可能的。

WAA做的是统一CSS动画,CSS过渡和SVG动画在一个通用的规范集下,并将提供一套统一的方法来控制动画。


I'm working on an image fader. I have it so that it fades the image (or in this case div with a background color) selected by the getElementById method, but I'm wondering how I can modify the JavaScript code to select all div elements and fade out, one after the other.

var c = document.getElementById("one");

function fade(){
  if (!c.style.opacity){
    c.style.opacity = 1;
  };
  
  var interval = setInterval (fadeout, 200);
  
  function fadeout(){
    c.style.opacity -= .05;
    
    if (c.style.opacity <= 0){
      clearInterval(interval);
    };
  };
};

fade();

#container{
  position: relative;
  margin: 0 auto;
  text-align: center;
  width: 350px;
  height: 350px;
  background-color: rgb(200,200,200);
}

.inner{
  position: absolute;
  margin: 0 auto;
  left: 25px;
  top: 25px;
  width: 300px;
  height: 300px;
}

#one{
  background-color: rgb(100,100,100);
}

#two{
  background-color: rgb(0,160,230);
}

#three {
  background-color: rgb(0,255,130);
}

#four{
  background-color: rgb(255,130,255);
}

<div id="container">
  <div class="inner" id="one"></div>
  <div class="inner" id="two"></div>
  <div class="inner" id="three"></div>
  <div class="inner" id="four"></div>
</div>

I also need a way (possibly making the function recursive) to keep going from four back to one, and I will not use jQuery for this.

解决方案

This is what you're looking for:

var interval = 4000,
  collection = document.querySelectorAll('#container>.inner');

for (var i = 0; i < collection.length; i++) {
  (function(i) {
    setTimeout(function() {
      collection[collection.length - i - 1].style.opacity = 0;
    }, i * interval);
  })(i)
}

#container {
  position: relative;
  margin: 0 auto;
  text-align: center;
  width: 350px;
  height: 350px;
  background-color: rgb(200, 200, 200);
}

.inner {
  position: absolute;
  margin: 0 auto;
  left: 25px;
  top: 25px;
  width: 300px;
  height: 300px;
  transition: opacity 4s linear;
}

#one {
  background-color: rgb(100, 100, 100);
}

#two {
  background-color: rgb(0, 160, 230);
}

#three {
  background-color: rgb(0, 255, 130);
}

#four {
  background-color: rgb(255, 130, 255);
}

<div id="container">
  <div class="inner" id="one"></div>
  <div class="inner" id="two"></div>
  <div class="inner" id="three"></div>
  <div class="inner" id="four"></div>
</div>

To give it a more natural feel (impression of intent, gesture, livelyness) you need to change linear to the easing of your choice in CSS:

var interval = 4000,
  collection = document.querySelectorAll('#container>.inner');

for (var i = 0; i < collection.length; i++) {
  (function(i) {
    setTimeout(function() {
      collection[collection.length - i - 1].style.opacity = 0;
    }, i * interval);
  })(i)
}

#container {
  position: relative;
  margin: 0 auto;
  text-align: center;
  width: 350px;
  height: 350px;
  background-color: rgb(200, 200, 200);
}

.inner {
  position: absolute;
  margin: 0 auto;
  left: 25px;
  top: 25px;
  width: 300px;
  height: 300px;
  transition: opacity 4s cubic-bezier(.6, 0, .3, 1);
}

#one {
  background-color: rgb(100, 100, 100);
}

#two {
  background-color: rgb(0, 160, 230);
}

#three {
  background-color: rgb(0, 255, 130);
}

#four {
  background-color: rgb(255, 130, 255);
}

<div id="container">
  <div class="inner" id="one"></div>
  <div class="inner" id="two"></div>
  <div class="inner" id="three"></div>
  <div class="inner" id="four"></div>
</div>

Principle: whenever you want to stagger animations (repeat exact same animation on a collection of elements), chaining the start of one animation upon the end of the previous is, to say the least, improper. You are limiting yourself to always having to wait for one animation to end in order to start the next. But you normally want this behavior when the duration of an action is unknown at the time you are executing the script. Here, it's the same duration so chaining is only a useless limitation.

Instead, use setTimeout() on the collection and you will end up having the option of animating multiple elements at any given moment and having better (separated) controls over animation details (duration, timing function and stagger step).

Another big problem with your approach is you're making 20 changes for each element, instead of only one. CSS animations give you control over animation-duration, animation-timing-function (very important when animating movement) and animation-delay (not used here). Besides, it's smoother and lighter on the browser.

I'll exemplify below, by animating movement instead of opacity:

// only set the stagger step and the collection in js
// set animation duration and easing in CSS for best results

var interval = 63, // stagger step
  collection = document.querySelectorAll('div');
// in your case, use document.querySelectorAll('#container>.inner');

for (var i = 0; i < collection.length; i++) {
  (function(i) {
    setTimeout(function() {
      collection[i].style.transform = 'translateX(0)';
    }, i * interval);
  })(i)
}

div {
  background-color: #ddd;
  margin-top: 1px;
  min-height: .5rem;
  transform: translateX(100%);
  /* here it is: duration 300ms, and transition
   * I've put in cubic, as it's good for staggered movement
   * it looks natural. For opacity it doesn't matter
   * it can be linear, ease-out, anything.
   */
  transition: transform 1s cubic-bezier(.5, 0, .1, 1);
}

body {
  overflow-x: hidden;
  margin: 0;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>


Initial answer, before noticing a jQuery free solution is required:

// only set the stagger step and the collection in js
// set animation duration and easing in CSS for best results

var interval = 42, // stagger step
  collection = $('div'); // in your case, use $('#container>.inner');

collection.each(function(i) {
  setTimeout(function() {
    collection.eq(i).css('opacity', 0);
  }, i * interval);
})

div {
  background-color: #ddd;
  margin-top: 1px;
  min-height: .5rem;
  /* here it is: duration 300ms, and transition
   * I've put in cubic, as it's good for staggered movement
   * it looks natural. For opacity it doesn't matter
   * it can be linear, ease-out, anything.
   */
  transition: opacity 300ms cubic-bezier(.4, 0, .2, 1);
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>    <div></div>    <div></div>
<div></div>


End note: This answer did not even touch the new (and promising) way to animate: Web Animations Api, because it's still experimental tech.
WAA animates using chaining but provides methods to cancel animation requests. It works in all major browsers and can be used with polyfill in older browsers.
It will probably gain huge popularity once Android browsers will support it. Until then, the best way to animate is using CSS animations and transitions which, even if not declaratively, also support canceling a request: you just change the property and it automatically starts a new animation on the same property from the current state, canceling the old one. The only CSS current limitation is that it won't calculate the new duration based on how much of the old one has been completed, which is possible in WAA.
What WAA does is unifying CSS animations, CSS transitions and SVG animations under one, common set of specs and will provide a unified set of methods for controlling animations.

这篇关于如何一个接一个地修改多个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆