我正在构建一个循环遍历3个不同背景的页面,每750毫秒更换一次。要做到这一点,我将使用相关的背景图像向主体添加一个类,并使用JS进行更改。对于第一个循环,它们会闪烁,因为图像必须加载,所以它不会立即出现。因此,有什么方法可以用来预加载图像吗?
CSS:
&.backgrounds{
background-position: center bottom;
background-repeat: no-repeat;
background-size: 130%;
&.freddy{
background-image: url(/img/illustrations/snapchat/snapchat_holding_page_freddy.jpg);
}
&.irene{
background-image: url(/img/illustrations/snapchat/snapchat_holding_page_irene.jpg);
}
&.joe{
background-image: url(/img/illustrations/snapchat/snapchat_holding_page_joe.jpg);
}
}
JS:
setInterval(function() {
if ( $('.backgrounds').hasClass('freddy') ){
$('.backgrounds').removeClass('freddy').addClass('irene');
} else if ( $('.backgrounds').hasClass('irene') ){
$('.backgrounds').removeClass('irene').addClass('joe');
} else if ( $('.backgrounds').hasClass('joe') ){
$('.backgrounds').removeClass('joe').addClass('freddy');
}
}, 750);
答案 0 :(得分:4)
我会做这样的事情。 loadImages
返回一个Promise,一旦加载了所有图像,它将解析。附加到它的.then
调用cycleImages
,启动间隔。既然你需要JS中的URL来进行预加载,而不是类切换我直接操作background-image
,这样你就可以从CSS中删除图像URL并节省一些冗余字节。这也使得将来更容易扩展图像列表,您只需要在图像数组中添加项目,而不是维护复杂的if语句。
function loadImages (images) {
// each image will be loaded by this function.
// it returns a Promise that will resolve once
// the image has finished loading
let loader = function (src) {
return new Promise(function (resolve, reject) {
let img = new Image();
img.onload = function () {
// resolve the promise with our url so it is
// returned in the result of Promise.all
resolve(src);
};
img.onerror = function (err) {
reject(err);
};
img.src = src;
});
};
// create an image loader for each url
let loaders = [];
images.forEach(function (image) {
loaders.push(loader(image));
});
// Promise.all will return a promise that will resolve once all of of our
// image loader promises resolve
return Promise.all(loaders);
}
// the images we are going to display
let myImages = [
'http://www.gifpng.com/400x200',
'http://www.gifpng.com/400x200/ffffff/000000',
'http://www.gifpng.com/400x200/000000/ffffff'
];
// $(document).ready(fn) is deprecated,
// use the $(fn) form instead
$(function() {
// after the images are loaded this will be called with an array of the loaded images
function cycleImages (images) {
let index = 0;
setInterval(function() {
// since we need an array of the image names to preload them anyway,
// just load them via JS instead of class switching so you can cut them
// out of the CSS and save some space by not being redundant
$('#backgrounds').css('backgroundImage', 'url("' + images[index] + '")');
// increment, roll over to 0 if at length after increment
index = (index + 1) % images.length;
}, 750);
}
// load the images and start cycling through them after they are loaded
loadImages(myImages).then(cycleImages).catch(function (err) {
console.error(err);
});
});
#backgrounds {
height: 200px;
width: 400px;
border: 1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="backgrounds"></div>
修改强>
考虑到Just a student的注释,这里的版本只会在加载后切换图像,但如果加载后立即执行。它还会跳过无法加载的图像。由于cycleImages
不再通过.then
调用,我也改变了它,因此它接受一个目标元素(作为jQuery对象)以及一系列图像承诺。这样,如果您愿意,可以在具有不同图像集的页面上的多个位置轻松使用它。
function loadImages (images) {
// each image will be loaded by this function.
// it returns a Promise that will resolve once
// the image has finished loading
let loader = function (src) {
return new Promise(function (resolve, reject) {
let img = new Image();
img.onload = function () {
// resolve the promise with our url
resolve(src);
};
img.onerror = function (err) {
reject(err);
};
img.src = src;
});
};
// return an array of image-loading promises
return images.map(function (image) {
return loader(image);
});
}
// the images we are going to display
let myImages = [
'http://www.gifpng.com/400x200',
'http://www.invalid-domain-name.foo/this-url-certainly-does-not-exist.jpg',
'http://www.gifpng.com/400x200/ffffff/000000',
'http://www.gifpng.com/400x200/000000/ffffff'
];
// $(document).ready(fn) is deprecated,
// use the $(fn) form instead
$(function() {
// this receives an array of the promises for each image
function cycleImages ($target, images) {
let index = 0,
interval = 750; // how many ms to wait before attempting to switch images
function nextImage () {
// p is the promise for the current image
let p = images[index],
next = function (wait) {
// increment our counter and wait to display the next one
index = (index + 1) % images.length;
setTimeout(nextImage, wait);
};
// wait for this image to load or fail to load
p.then(function (src) {
// it loaded, display it
$target.css('backgroundImage', 'url("' + src + '")');
next(interval);
}).catch(function (err) {
// this one failed to load, skip it
next(0);
});
}
// start cycling
nextImage();
}
// load the images and start cycling through them as they are loaded
cycleImages($('#backgrounds'), loadImages(myImages));
});
#backgrounds {
height: 200px;
width: 400px;
border: 1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="backgrounds"></div>
您可以将其作为参数传递,而不是对图像之间的间隔进行硬编码。在那时,我会重构它以使用配置对象传递除映像承诺数组之外的所有内容:cycleImages(myImages, {target: $('#backgrounds'), interval: 1000});
答案 1 :(得分:1)
您可以在javascript中加载它们。像:
(new Image()).src = url1;
(new Image()).src = url2;
(new Image()).src = url3;
更改&#34; url1&#34;,&#34; url2&#34;,&#34; url3&#34;与你自己的图像网址。浏览器将加载图像,但它们在任何地方都不可见。
答案 2 :(得分:0)
有趣的想法。
你是否可以在后台加载它们,如:
<div class="hidden-images">
<img src="img1.jpg" />
<img src="img2.jpg" />
<img src="img3.jpg" />
</div>
然后在CSS中
.hidden-images {
position: relative;
z-index: 1;
}
然后,无论你主要的容器div是什么,在它上面打下一个?
.main-container {
position: relative;
z-index: 2; // Or higher, whatever is needed
}
答案 3 :(得分:0)
您也可以使用不同的html和css结构来执行此操作。
HTML
<div class="backgrounds">
<div class="background freddy"></div>
</div>
CSS
.backgrounds{
background-color: transparent;
background-position: center bottom;
background-repeat: no-repeat;
background-size: 130%;
height: 250px;
width; 100%;
}
.backgrounds .freddy{
height: 100%;
width: 100%;
background-image: url('http://adrianweb.net/includes/images/hero.jpg');
}
.backgrounds .irene{
height: 100%;
width: 100%;
background-image: url('http://adrianweb.net/includes/images/projects-blur.png');
}
.backgrounds .joe{
height: 100%;
width: 100%;
background-image: url('http://adrianweb.net/includes/images/contacts-blur.png');
}
JS
$(document).ready(function(){
setInterval(function() {
if ( $('.background').hasClass('freddy') ){
$('.background').removeClass('freddy').addClass('irene');
} else if ( $('.background').hasClass('irene') ){
$('.background').removeClass('irene').addClass('joe');
} else if ( $('.background').hasClass('joe') ){
$('.background').removeClass('joe').addClass('freddy');
}
}, 750);
});
也许你可以添加转换/动画来让它看起来淡入淡出。
下面的示例代码: