使用 for each 和 setTimeout 无限次迭代数组
Iterate an array infinite times with for each and setTimeout
我在myClass
中有这个方法。当它到达数组的末尾时,我希望它从 0 重新开始,但是此时它只是停止了。
this.jsonParse = function() {
for (var i = 0; i < this.numberOfPhotos; i++){
(function(index, selector, timing, arrayLength){
setTimeout(function() {
$(selector).css('background-color': obj_gallery.images[index].hex);
}, index*timing);
})(i, this.slideWrap, this.timing,this.numberOfPhotos);
}
}
我在下面尝试过类似的方法,但它不起作用。
if (index >= arrayLength) {
index = 0;
}
NB this.numberOfPhotos
等局部变量已经定义好了
我想你可能想改用 setInterval() - http://codepen.io/anon/pen/ogVodo
this.jsonParse = function(){
// Ho bisogno di una funziona anonimica per passare i parametri, poiche il setTimeout non lo fa.
var slideWrap = this.slideWrap;
var timing = this.timing;
var numberOfPhotos = this.numberOfPhotos;
var index =0;
setInterval(function() {
$(".gallery").css('background-color', obj_gallery.images[index].hex);
index++;
if (index === numberOfPhotos){
index = 0;
}
},timing);
};
我会建议使用递归而不是增量超时的不同方法。首先,我将创建一个您可以重复使用的抽象:
function cycle(delay, f, xs) {
var run = function(i) {
setTimeout(function() {
f(xs[i])
i += 1
if (i >= xs.length) {
i = 0
}
run(i)
}, delay)
}
f(xs[0])
run(1)
}
那么您可以进行以下操作:
this.jsonParse = function(){
var $el = $(this.slideWrap)
var bgcolor = function(img) {
$el.css('background-color', img.hex)
}
cycle(this.timing, bgcolor, obj_gallery.images)
};
例如:DEMO
虽然我想我明白你想做什么(无限期地旋转图像),但你的方法相当糟糕。假设轮换中有 1000 张图像,则至少有 1000 个计时器 运行 并且一次加载所有 1000 张图像。
相反,我会使用一种简单得多的方法,在您的索引上使用模运算符,并使用一个简单的函数来更新两个图库图像之一。
首先,基本的HTML非常简约:
<div id="gallery">
<img id="gallery_a" onload="galleryLoaded()" />
<img id="gallery_b" onload="galleryLoaded()" />
</div>
onload
事件用于在加载图像后实际切换可见图像,并防止在加载完成之前切换图像。
我已经设置 an example on JSFiddle 来展示这种方法。
这不需要特殊的 CSS。为了使过渡效果起作用,您需要对第二张图片进行一些最小设置:
#gallery_b {
opacity: 0;
transition: opacity 1s;
}
定期调用的函数(也可能由按钮或某些 link 启动)将更新当前图像的索引并交换当前不可见的图像:
// This function will init the switch
function galleryNext() {
if (gallery_switching)
return;
// Prevent multiple switches at once
gallery_switching = true;
// Get the next index (the modulo will make it wrap around)
gallery_index = (gallery_index + 1) % images.length;
// Update the inactive image
// This could also update some link target or similar
document.getElementById(gallery_second ? 'gallery_a' : 'gallery_b').src = images[gallery_index];
// Toggle the next image
gallery_second = !gallery_second;
}
onload
事件将切换图像(基本上只是根据需要隐藏第二个图像):
// This function is a callback once the next image has been loaded
function galleryLoaded() {
if (!gallery_switching)
return;
gallery_switching = false;
// If the second image is the next, we'll have to hide it now (since we want to show the first one)
document.getElementById('gallery_b').style.opacity = gallery_second ? 1 : 0;
}
最后但同样重要的是,您必须设置间隔并立即显示第一张图片。
setTimeout(galleryNext, 0); // Fake "onload" here
setInterval(galleryNext, 2500); // Switch once every 5 seconds
当然,您也可以在其他地方为图像设置初始 src
。
我在myClass
中有这个方法。当它到达数组的末尾时,我希望它从 0 重新开始,但是此时它只是停止了。
this.jsonParse = function() {
for (var i = 0; i < this.numberOfPhotos; i++){
(function(index, selector, timing, arrayLength){
setTimeout(function() {
$(selector).css('background-color': obj_gallery.images[index].hex);
}, index*timing);
})(i, this.slideWrap, this.timing,this.numberOfPhotos);
}
}
我在下面尝试过类似的方法,但它不起作用。
if (index >= arrayLength) {
index = 0;
}
NB this.numberOfPhotos
等局部变量已经定义好了
我想你可能想改用 setInterval() - http://codepen.io/anon/pen/ogVodo
this.jsonParse = function(){
// Ho bisogno di una funziona anonimica per passare i parametri, poiche il setTimeout non lo fa.
var slideWrap = this.slideWrap;
var timing = this.timing;
var numberOfPhotos = this.numberOfPhotos;
var index =0;
setInterval(function() {
$(".gallery").css('background-color', obj_gallery.images[index].hex);
index++;
if (index === numberOfPhotos){
index = 0;
}
},timing);
};
我会建议使用递归而不是增量超时的不同方法。首先,我将创建一个您可以重复使用的抽象:
function cycle(delay, f, xs) {
var run = function(i) {
setTimeout(function() {
f(xs[i])
i += 1
if (i >= xs.length) {
i = 0
}
run(i)
}, delay)
}
f(xs[0])
run(1)
}
那么您可以进行以下操作:
this.jsonParse = function(){
var $el = $(this.slideWrap)
var bgcolor = function(img) {
$el.css('background-color', img.hex)
}
cycle(this.timing, bgcolor, obj_gallery.images)
};
例如:DEMO
虽然我想我明白你想做什么(无限期地旋转图像),但你的方法相当糟糕。假设轮换中有 1000 张图像,则至少有 1000 个计时器 运行 并且一次加载所有 1000 张图像。
相反,我会使用一种简单得多的方法,在您的索引上使用模运算符,并使用一个简单的函数来更新两个图库图像之一。
首先,基本的HTML非常简约:
<div id="gallery">
<img id="gallery_a" onload="galleryLoaded()" />
<img id="gallery_b" onload="galleryLoaded()" />
</div>
onload
事件用于在加载图像后实际切换可见图像,并防止在加载完成之前切换图像。
我已经设置 an example on JSFiddle 来展示这种方法。
这不需要特殊的 CSS。为了使过渡效果起作用,您需要对第二张图片进行一些最小设置:
#gallery_b {
opacity: 0;
transition: opacity 1s;
}
定期调用的函数(也可能由按钮或某些 link 启动)将更新当前图像的索引并交换当前不可见的图像:
// This function will init the switch
function galleryNext() {
if (gallery_switching)
return;
// Prevent multiple switches at once
gallery_switching = true;
// Get the next index (the modulo will make it wrap around)
gallery_index = (gallery_index + 1) % images.length;
// Update the inactive image
// This could also update some link target or similar
document.getElementById(gallery_second ? 'gallery_a' : 'gallery_b').src = images[gallery_index];
// Toggle the next image
gallery_second = !gallery_second;
}
onload
事件将切换图像(基本上只是根据需要隐藏第二个图像):
// This function is a callback once the next image has been loaded
function galleryLoaded() {
if (!gallery_switching)
return;
gallery_switching = false;
// If the second image is the next, we'll have to hide it now (since we want to show the first one)
document.getElementById('gallery_b').style.opacity = gallery_second ? 1 : 0;
}
最后但同样重要的是,您必须设置间隔并立即显示第一张图片。
setTimeout(galleryNext, 0); // Fake "onload" here
setInterval(galleryNext, 2500); // Switch once every 5 seconds
当然,您也可以在其他地方为图像设置初始 src
。