Javascript 每分钟变换一次背景图像

Javascript 每分钟变换一次背景图像,javascript,html,jquery,css,background-image,Javascript,Html,Jquery,Css,Background Image,我目前正在开发一个私人仪表盘。这个仪表板应该有每分钟都在变化的背景图像(如果我当时让它工作的话,切换到1小时或20秒应该没有问题) 为此,我注册了[Pixabay API][1],并创建了以下API请求 通过该请求,我得到一个包含100个元素的数组,每个元素包含以下信息: comments: 639 downloads: 785498 favorites: 3020 id: 736885 imageHeight: 1195 imageSize: 186303 imageWidth: 1920

我目前正在开发一个私人仪表盘。这个仪表板应该有每分钟都在变化的背景图像(如果我当时让它工作的话,切换到1小时或20秒应该没有问题)

为此,我注册了[Pixabay API][1],并创建了以下API请求

通过该请求,我得到一个包含100个元素的数组,每个元素包含以下信息:

comments: 639
downloads: 785498
favorites: 3020
id: 736885
imageHeight: 1195
imageSize: 186303
imageWidth: 1920
largeImageURL: "https://pixabay.com/get/51e3d34b4257b108f5d0846096293076123ddee2504c704c7c2879d79048c05a_1280.jpg"
likes: 3966
pageURL: "https://pixabay.com/photos/tree-sunset-amazing-beautiful-736885/"
previewHeight: 93
previewURL: "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_150.jpg"
previewWidth: 150
tags: "tree, sunset, amazing"
type: "photo"
user: "Bessi"
userImageURL: "https://cdn.pixabay.com/user/2019/04/11/22-45-05-994_250x250.jpg"
user_id: 909086
views: 2042402
webformatHeight: 398
webformatURL: "https://pixabay.com/get/51e3d34b4257b10ff3d8992cc62f3f79173fd9e64e507440722d78d39248c7_640.jpg"
webformatWidth: 640
从这100个元素中,我随机选择一个,以
largeImageURL
为背景,加上半透明的深色覆盖层,以便更好地阅读上面的文本。所有这些都是在
设置间隔内完成的,因此每x毫秒发生一次

这是它的代码:

setInterval(function(){
        $.post('getBackgroundImages.php', {  }, function(data) {
        var imageCollection = JSON.parse(data);
        var imageNumber = Math.floor(Math.random() * 100);
        var imageLink = imageCollection.hits[imageNumber].largeImageURL;
        $('body').css("background","linear-gradient(rgba(0,0,0,.3), rgba(0,0,0,.3)),url('"+imageLink+"')");
    });
},60000);
`php'只不过是打印API请求的内容

现在的问题是:在实现的解决方案中,一切正常,新照片显示为背景,切换正常。但是,在显示图像之前,背景始终设置为灰色背景大约半秒钟,这看起来确实不好,尤其是在经常切换图像时

我想得到的是在短时间内没有灰色背景的情况下切换背景,很可能即使有过渡,所以变化也不会那么突然

我找到了一个解决方案,在显示全分辨率图像之前,先显示图像的模糊预览。然而,我认为这不应该是必要的,因为基本上,图像有足够的时间加载,并且在加载图像后背景应该改变。。我不在乎是否每62秒更改一次,即使我将其设置为60秒,因为需要先加载图像

有谁能给我一个如何使这项工作更好的提示吗

提前谢谢!
[1] :

也许最简单的方法是在两个类似于背景的容器之间切换:

HTML:

<body>
    <div class='bg' id='firstBg'></div>
    <div class='bg' id='secondBg'></div>

    <...Your Stuff...>

</body>
JS:


由于@zero298的提示,我现在执行了以下解决方案

<script>
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);
}

 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
      $('body').css("background","linear-gradient(rgba(0,0,0,.3), rgba(0,0,0,.3)),url('"+images[index]+"')");
      // increment, roll over to 0 if at length after increment
      index = (index + 1) % images.length;
    }, 28800000);
  }

$(function(){
    $.post('getBackgroundImages.php', {  }, function(data) {
        var imageCollection = JSON.parse(data);
        var imageNumber = Math.floor(Math.random() * 100);
        var imageLink = imageCollection.hits[imageNumber].largeImageURL;
        $('body').css("background","linear-gradient(rgba(0,0,0,.3), rgba(0,0,0,.3)),url('"+imageLink+"')");
    });
    $.ajax('getBackgroundImages.php',{
        success:function(data) {
            var parsed = JSON.parse(data);
            var images = parsed.hits;
            var imageUrls = [];
            images.forEach(function(item,index){
                imageUrls.push(item.largeImageURL);
            })
            loadImages(imageUrls).then(cycleImages).catch(function (err) {
                console.error(err);
            });
        }   
    });
});
</script>

函数加载图像(图像){
//此函数将加载每个图像。
//它返回一个承诺,该承诺将一次性解决
//图像已完成加载
let loader=函数(src){
返回新承诺(功能(解决、拒绝){
设img=新图像();
img.onload=函数(){
//用我们的url解析承诺,使其成为
//在承诺的结果中返回。全部
决议(src);
};
img.onerror=函数(err){
拒绝(错误);
};
img.src=src;
});
};
//为每个url创建一个图像加载器
让loaders=[];
image.forEach(函数(图像){
加载器。推(加载器(图像));
});
//承诺。所有人都会回报一个承诺,这个承诺将在我们所有人
//图像加载器承诺解决
归还承诺。所有(装载机);
}
函数循环图像(图像){
设指数=0;
setInterval(函数(){
//因为我们需要一个图像名称数组来预加载它们,
//只需通过JS加载它们,而不是类切换,这样您就可以剪切它们
//使用CSS,并通过不冗余来节省一些空间
$('body').css(“背景”、“线性渐变(rgba(0,0,0.3)、rgba(0,0,0.3))、url(“+”图像[索引]+”)”);
//增量,如果增量后的长度为0,则滚动到0
索引=(索引+1)%images.length;
}, 28800000);
}
$(函数(){
$.post('getBackgroundImages.php',{},函数(数据){
var imageCollection=JSON.parse(数据);
var imageNumber=Math.floor(Math.random()*100);
var imageLink=imageCollection.hits[imageNumber].largeImageURL;
$('body').css(“背景”、“线性渐变”(rgba(0,0,0,3)、rgba(0,0,0,3))、url(“+imageLink+”)”);
});
$.ajax('getBackgroundImages.php'{
成功:功能(数据){
var parsed=JSON.parse(数据);
var images=parsed.hits;
var-imageurl=[];
image.forEach(函数(项、索引){
push(item.largeImageURL);
})
loadImages(imageUrls).then(cycleImages.catch(函数(err)){
控制台错误(err);
});
}   
});
});
这首先将所有ImageURL放入一个数组,然后加载带有
Promise
的所有图像,然后立即显示。。我并没有在切换图像之间进行很好的转换,因为
jQuery
s fade to方法让页面内容也淡出,而不仅仅是背景图像

顺便说一句,添加更多div/更改页面结构并不容易,因为有很多浮动和其他css规则使元素出现在页面的不同位置。在所有内容周围添加一个div,以便尝试为该div提供背景图像,从而破坏了孔布局


总而言之,我对这个解决方案很有信心,但是,如果有人有让切换更平滑的好主意,请随时告诉我:)

也许可以尝试预热图像缓存,作为实际执行转换的先决条件。查看是否执行以下操作:缓存实际图像并准备立即显示,然后执行转换。我不知道问题是是否存在中间灰色背景,还是没有加载图像并出现“弹出”现象。您不需要通过画布进行渲染,只需要浏览器不需要单独的请求。@Zero298使用javascripts
promise
的提示就可以工作了。。。现在图像变化大约在100毫秒内发生,所以可以接受。。。现在,我正在尝试在那里进行转换,因此更改不会太剧烈。如果您尝试交叉淡入淡出,则可能需要2个容器元素。在纯CSS中,还没有一种干净的方法可以对图像背景进行交叉淡入。这就是为什么
setInterval(function(){
    $.post('getBackgroundImages.php', {  }, function(data) {
        var imageCollection = JSON.parse(data);
        var imageNumber = Math.floor(Math.random() * 100);
        var imageLink = imageCollection.hits[imageNumber].largeImageURL;
        if ($('#firstBg').css('display') == 'none') {
            $('#firstBg').css("background-image","url('"+imageLink+"')");
            $('#firstBg').fadeIn();
            $('#secondBg').fadeOut();
        }
        else {
            $('#secondBg').css("background-image","url('"+imageLink+"')");
            $('#secondBg').fadeIn();
            $('#firstBg').fadeOut(); 
        }
    });
},60000);
<script>
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);
}

 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
      $('body').css("background","linear-gradient(rgba(0,0,0,.3), rgba(0,0,0,.3)),url('"+images[index]+"')");
      // increment, roll over to 0 if at length after increment
      index = (index + 1) % images.length;
    }, 28800000);
  }

$(function(){
    $.post('getBackgroundImages.php', {  }, function(data) {
        var imageCollection = JSON.parse(data);
        var imageNumber = Math.floor(Math.random() * 100);
        var imageLink = imageCollection.hits[imageNumber].largeImageURL;
        $('body').css("background","linear-gradient(rgba(0,0,0,.3), rgba(0,0,0,.3)),url('"+imageLink+"')");
    });
    $.ajax('getBackgroundImages.php',{
        success:function(data) {
            var parsed = JSON.parse(data);
            var images = parsed.hits;
            var imageUrls = [];
            images.forEach(function(item,index){
                imageUrls.push(item.largeImageURL);
            })
            loadImages(imageUrls).then(cycleImages).catch(function (err) {
                console.error(err);
            });
        }   
    });
});
</script>