逐个更改项目的颜色

change color of items one by one

本文关键字:颜色 项目      更新时间:2023-09-26

我编写了一个脚本,该脚本创建了一组排列在圆圈中的小圆圈,这些圆圈通过循环一个接一个地添加到DOM中。在第一个循环完成后(所以我希望这是当i == 54),我想开始另一个循环,从列表中的第一个圆圈开始,一个接一个地将圆圈的颜色从灰色变为红色。

这是我的代码:

var i = 1;
var appendCircle = function loop() {
  setTimeout(function() {
    var $circle = "<div class='circle circle" + i + "' style='transform:rotate(" + 7.2 * i + "deg) translate(3em)'></div>";
    var $container = $(".circles-wrapper .circles");
    $container.append($circle);
    i++;
    if (i < 55) {
      loop();
    }
  }, 20);
  // this is the problem because this change color of all small circles at once.
  if (i == 54) {
    setTimeout(function() {
      $(".circle").each(function() {
        $(this).css({
          "background": "blue"
        });
      })
    }, 20);
  }
};
setTimeout(appendCircle, 100);
.circles-wrapper {
  position: absolute;
  top: 39%;
  left: 51%;
}
.circles {
  position: relative;
  transform: rotateY(48deg);
}
.circle {
  width: .2em;
  height: .2em;
  margin: -.2em;
  border-radius: 50%;
  background: #ceced0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="circles-wrapper">
  <div class="circles"></div>
</div>

你给每个圆圈类"circle"+index,所以你所要做的就是遍历每个索引并改变每个元素的背景颜色。我所做的是使用相同的循环函数,当我达到55后,我对它取mod 55,并使用它来选择圆。下面的代码和片段。

我还注意到一些圆圈重叠。如果你生成50个圆,就不会有任何重叠。我写了下面的代码来反映这一点。

var i = 1;
var appendCircle = function loop() {
  setTimeout(function() {
    if (i < 51) {
		var $circle = "<div class='circle circle" + i + "' style='transform:rotate(" + 7.2 * i + "deg) translate(3em)'></div>";
		var $container = $(".circles-wrapper .circles");
		$container.append($circle);
    }
	else{
		var circleIndex = (i % 51)+1;
		$(".circle"+circleIndex).css("background-color", "blue");
	}
	
	if(i<109){
		loop();
	}
	i++;
  }, 20);
};
setTimeout(appendCircle, 100);
.circles-wrapper {
  position: absolute;
  top: 39%;
  left: 51%;
}
.circles {
  position: relative;
  transform: rotateY(48deg);
}
.circle {
  width: .2em;
  height: .2em;
  margin: -.2em;
  border-radius: 50%;
  background: #ceced0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="circles-wrapper">
  <div class="circles"></div>
</div>

在您第一次传递之后,您可能想要找到创建的圆圈并修改它们。你给他们上了一堂circle + i课,这样你就能很容易地找到他们。检查代码片段。我加了第三遍只是因为。

var i = 1,
  CIRCLE_COUNT = 52;
var appendCircle = function loop() {
  setTimeout(function() {
    i++;
    // first pass
    if (i < CIRCLE_COUNT * 1) {
      var $circle = "<div class='circle circle" + i + "' style='transform:rotate(" + 7.2 * i + "deg) translate(3em)'></div>";
      var $container = $(".circles-wrapper .circles");
      $container.append($circle);
    } 
    // second pass
    else if (i < CIRCLE_COUNT * 2) {
      $(".circle" + (i % CIRCLE_COUNT+1)).css('background', 'blue');
    }
    
    // third pass
    else if (i < CIRCLE_COUNT * 3) {
      $(".circle" + (i % CIRCLE_COUNT+1)).remove();
    }
    
    // keep looping?
    if (i <= CIRCLE_COUNT * 3)
      loop();
  }, 20);
};
setTimeout(appendCircle, 100);
.circles-wrapper {
  position: absolute;
  top: 39%;
  left: 51%;
}
.circles {
  position: relative;
  transform: rotateY(48deg);
}
.circle {
  width: .2em;
  height: .2em;
  margin: -.2em;
  border-radius: 50%;
  background: #ceced0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="circles-wrapper">
  <div class="circles"></div>
</div>

像这样?我在你的.each()中设置了一个超时函数,以便在每次循环迭代之间延迟,当你将圆圈的颜色更改为蓝色

var i = 1;
var appendCircle = function loop() {
  setTimeout(function() {
    var $circle = "<div class='circle circle" + i + "' style='transform:rotate(" + 7.2 * i + "deg) translate(3em)'></div>";
    var $container = $(".circles-wrapper .circles");
    $container.append($circle);
    i++;
    if (i < 55) {
      loop();
    }
  }, 20);
  // this is the problem because this change color of all small circles at once.
  if (i == 54) {
    var time = 50;
    $(".circle").each(function() {
      var $this = $(this)
      setTimeout(function(){
        $this.css({
          "background": "blue"
        }); 
      }, time)
      time += 50;
    });
  }
};
setTimeout(appendCircle, 100);
.circles-wrapper {
  position: absolute;
  top: 39%;
  left: 51%;
}
.circles {
  position: relative;
  transform: rotateY(48deg);
}
.circle {
  width: .2em;
  height: .2em;
  margin: -.2em;
  border-radius: 50%;
  background: #ceced0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="circles-wrapper">
  <div class="circles"></div>
</div>

您只需要更改一个元素的CSS,然后启动超时以更改下一个元素

var i = 1;
var appendCircle = function loop() {
  setTimeout(function() {
    var $circle = "<div class='circle circle" + i + "' style='transform:rotate(" + 7.2 * i + "deg) translate(3em)'></div>";
    var $container = $(".circles-wrapper .circles");
    $container.append($circle);
    i++;
    if (i < 55) {
      loop();
    }
  }, 20);
  var j = 0;
  function changeColor() {
    $(".circle").eq(j).css("background", "blue");
    j++;
    if (j >= $(".circle").length) {
      clearInterval(changeInterval);
    }
  }
  if (i == 53) {
    setInterval(changeColor, 20);
  }
}
setTimeout(appendCircle, 100);
.circles-wrapper {
  position: absolute;
  top: 39%;
  left: 51%;
}
.circles {
  position: relative;
  transform: rotateY(48deg);
}
.circle {
  width: .2em;
  height: .2em;
  margin: -.2em;
  border-radius: 50%;
  background: #ceced0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="circles-wrapper">
  <div class="circles"></div>
</div>

jQuery有一些特性可以使这样的动画变得相当简单,尽管您需要了解几个方法。

jQuery的.delay(), .promise(), .then()和javascript的Array.prototype.reduce()可以被利用如下:

var appendCircles = function($container) {
    //create and append hidden circles
    for(var i=0; i<50; i++) {
        $("<div class='circle'></div>").css('transform', 'rotate(' + 7.2 * i + 'deg) translate(3em)').hide().appendTo($container);
    }
    //find the freshly appended hidden circles
    var $circles = $container.find(".circle");
    //initial delay
    $circles.eq(0).delay(100).promise()
    .then(function() {
        //show the circles, one by one
        return $circles.get().reduce(function(promise, el) {
            return promise.then(function() {
                return $(el).show().delay(20).promise();
            });
        }, $.when());//$when() is a resolved promise that gets the built promise chain started
    })
    .then(function() {
        //make circles blue, one by one
        return $circles.get().reduce(function(promise, el) {
            return promise.then(function() {
                return $(el).css('backgroundColor', 'blue').delay(20).promise();
            });
        }, $.when());//$when() is a resolved promise that gets the built promise chain started
    });
};
appendCircles($(".circles"));

codepen

.reduce()可能需要一些解释。$circles.get()返回一个数组,.reduce(...)用于构建一个相当于initialPromise.then(...).then(...).then(...)的承诺链。这个把戏按顺序表演两次,以获得最初的"表演"效果,然后是颜色变化效果。

如果你想用jQuery制作自定义动画序列,这组方法值得学习。