支持事件的图像预加载器JavaScript
我正在尝试查找图像预加载器脚本。
虽然我发现了一些,但是没有一个支持预加载完成时触发的事件。
有谁知道任何脚本或jQuery插件,将这样做?
希望这个问题适合于stackoverflow – 如果不是,可以随时删除它。
这里有一个函数可以预先加载数组中的图像,并在最后一个完成时调用你的callback函数:
function preloadImages(srcs, imgs, callback) { var img; var remaining = srcs.length; for (var i = 0; i < srcs.length; i++) { img = new Image(); img.onload = function() { --remaining; if (remaining <= 0) { callback(); } }; img.src = srcs[i]; imgs.push(img); } } // then to call it, you would use this var imageSrcs = ["src1", "src2", "src3", "src4"]; var images = []; preloadImages(imageSrcs, images, myFunction);
而且,由于我们现在正处于使用asynchronous操作的承诺的时代,所以上面的版本使用promise,并通过ES6标准承诺通知调用者:
function preloadImages(srcs) { function loadImage(src) { return new Promise(function(resolve, reject) { var img = new Image(); img.onload = function() { resolve(img); }; img.onerror = img.onabort = function() { reject(src); }; img.src = src; }); } var promises = []; for (var i = 0; i < srcs.length; i++) { promises.push(loadImage(srcs[i])); } return Promise.all(promises); } preloadImages(["src1", "src2", "src3", "src4"]).then(function(imgs) { // all images are loaded now and in the array imgs }, function(errImg) { // at least one image failed to load });
而且,这里有一个使用2015年jQuery的承诺:
function preloadImages(srcs) { function loadImage(src) { return new $.Deferred(function(def) { var img = new Image(); img.onload = function() { def.resolve(img); }; img.onerror = img.onabort = function() { def.reject(src); }; img.src = src; }).promise(); } var promises = []; for (var i = 0; i < srcs.length; i++) { promises.push(loadImage(srcs[i])); } return $.when.apply($, promises).then(function() { // return results as a simple array rather than as separate arguments return Array.prototype.slice.call(arguments); }); } preloadImages(["src1", "src2", "src3", "src4"]).then(function(imgs) { // all images are loaded now and in the array imgs }, function(errImg) { // at least one image failed to load });
对于更强大的解决scheme,考虑这个PRELOADER
函数与几个callback( jsFiddle )。
保持简单:
在这个例子中,我在Object
字面值PRELOADER_OBJECT
传递callback函数和图像哈希值,然后覆盖PRELOADER
的callbackPRELOADER
:
// preloder object stores image hash // and event handler callbacks var PRELOADER_OBJECT = { imgArray:"http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg".split(" "), progressCallback : function( percent ) { $( '#preloader_progress' ).html( 'preload progress complete : ' + percent + '%' ); console.log( 'preload progress complete : ', percent ); }, completeCallback : function( scope ) { // hide preload indicator, do something when finished console.log( 'preload complete!' ); $( '#preloader_modal' ).delay( 1000 ).animate( { opacity : 0 }, function( ) { $( '.preload_class' ).each( function( index ) { $( this ).delay( index * 100 ).animate( { opacity : 0 } ); } ); } ); } /*Localize params and create PRELOADER object. Needs to loadImages( ); iterate through hash and call onPreloadProgress( ) and onPreloadComplete( ) each time until finished. If you're still within bounds of the image hash, call progressCallback( ) recursively. When finished, fire onCompleteCallback( )*/ var PRELOADER = function( object ) { // preloader modal overlay this.modal = undefined; // progress indicator container this.progressIndicator = undefined; // image preload progress this.progress = undefined; // progress callback this.progressCallback = undefined; // complete callback this.completeCallback = undefined; // hash to store key : value pairs for image paths this.imgArray = undefined; // store images in preloadArray this.preloadArray = []; // initialize and localize our data this.initialize = function( ) { // create preload indicator and overlay modal this.createPreloaderModal( ); // image hash this.imgArray = object.imgArray; // progress callback event handler this.progressCallback = object.progressCallback; // complete callback event this.completeCallback = object.completeCallback; // load images this.loadImages( ); }; this.progressCallback = function( ) {}; // function to override this.completeCallback = function( ) {}; // function to override // load images into DOM and fire callbacks this.loadImages = function( ) { var that = this; // iterate through hash and place images into DOM $.each( PRELOADER_OBJECT.imgArray, function( index, object ) { this.image = $( "<img/>", { "src" : object, "class": "preload_class" } ).appendTo( 'body' ); // mark progress and call progressCallback( ) event handler that.progress = Math.ceil( ( index / PRELOADER_OBJECT.imgArray.length ) * 100 ); that.progressCallback( this.progress ); that.preloadArray.push( this.image ); } ); // check for array bounds and call completeCallback( ) if ( PRELOADER_OBJECT.imgArray.length ) { this.progressCallback( 100 ); this.completeCallback( this ); } }; // create modal to display preload data this.createPreloaderModal = function( ) { this.modal = $( '<div/>', { 'id' : 'preloader_modal' } ).appendTo( 'body' ); this.progressIndicator = $( '<h1/>', { 'id' : 'preloader_progress' } ).appendTo( this.modal ); }; }; // trigger event chain when DOM loads $( document ).ready( function( ) { // instantiate PRELOADER instance and pass // our JSON data model as a parameter var preloader = new PRELOADER( PRELOADER_OBJECT ); // initialize preloader preloader.initialize( ); } );
};
由于网站负载足够大,需要一个图像预加载器,模式文本显示可以很容易地修改,以支持数据驱动的jQueryanimation。
预加载和加载是一回事。 你可以插入图像(或者创build一个新图像或者改变现有图像的“src”属性),但是使用$("element").hide()
或类似的东西来$("element").hide()
。 在你这样做之前,附加一个加载事件处理程序,如下所示:
var images = ["src1", "src2", "src3", "src4"]; var len = images.length; for(i=0; i<len; i++){ $("parent element").html('<img id="new-img" style="display:none;" src="'+images[i]+'"/>'); $("new-img").load(function(){ //Your image is now "preloaded" //Now you can show the image, or do other stuff $(this).show(); }); }
预加载需要一些额外的工作,比如创build新的图像元素,监视是否全部加载,然后用DOM中的现有元素replace它们。 但是,您可以无限次地直接在DOM <img>
元素上直接执行此操作,而无需replace它们。
我们可以使用Fetch API来访问这些图像,等待它们全部下载到promise.all()
,然后一次性使用window.requestAnimationFrame()
在最合适的时间replaceimg
元素的src
属性。 。
在下面的例子中,我刷新了img
元素的src
属性10次。 根据延迟,我正在使用从API加载4个图像所需的时间。 所以一旦我们加载了所有的图像,我立即通过recursion调用相同的refreshImagesNTimes
函数来发出一个新的请求。
您当然可以select一次载入尽可能多的图像斑点,并通过一个简单的setTimeout
机制以精确的时间间隔将它们分组显示。
function refreshImagesNTimes(nodeList,count = -1){ var imgPromises = Array.from({length: nodeList.length}) .map(_ => fetch("https://unsplash.it/480/640/?random").then(res => res.blob())); Promise.all(imgPromises) .then(function(blobs){ window.requestAnimationFrame(_ => nodeList.forEach((img, i) => img.src = (window.URL || window.webkitURL).createObjectURL(blobs[i]))); --count && refreshImagesNTimes(nodeList, count); }); } var images = document.querySelectorAll("#container img"); refreshImagesNTimes(images,10);
#container { display: flex; flex-wrap: wrap; justify-content: space-evenly; align-items: center; margin: auto; width: 75vw; height: 56.25vw; background-color: #000; box-sizing: border-box; } img { width: 45%; height: 45%; background-color: thistle; }
<div id="container"> <img> <img> <img> <img> </div>