Skip to content

PreloadJS

何波 edited this page Feb 23, 2019 · 3 revisions

https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/

PreloadJS介绍

一个可以让你管理和加载各种资源的库,通过tag或XHR的方式进行加载,可以加载的类型有Image,CSS,JS,Audio,JSON,JSONP,XML ,Font,SVG

LoadQueue 核心类

Extends AbstractLoader

默认情况下PreloadJS将尝试使用XHR加载内容,因为XHR提供了更好的支持和各种事件,然而由于跨域问题,它可能仍然倾向于使用基于标签的加载方式。注意,有些内容需要XHR(纯文本、网络音频),和一些需要标签Tag(HTML音频),不需要设置,自动处理。

基本概念:

  • 加载项(LoadItem):一个对象,该对象用于描述将要被加载的文件资源(如:id,ext,type,src,tag,path,crossOrign)。

  • 加载器:用于加载文件的插件。(如:TagLoader,XHRLoader)

  • 加载事件:文件加载过程中的各种事件。(如: progress, complete, fileload)

执行步骤

  1. LoadQueue 会为每个资源生成对应的加载项, 当检测到要加载的资源是对象且为 HTMLAudioElement 时, 将资源的 type 属性值设置为“ sound”。

  2. 当加载项生成完毕时, LoadQueue 会为每个资源生成一个加载器。( 当检测到加载项是文本或XML, LoadQueue 会强制生成 XHRLoader 加载器,当检测到加载项是音频时, LoadQueue 会强制生成 TagLoader 加载器。 其他情况则根据实例化 LoadQueue 时传入的参数生成对应加载器。)

  3. LoadQueue 会把每个资源的加载器, 加入一个队列中。

  4. 为每个加载器绑定加载事件。( progress, complete, error)

  5. 按队列顺序执行每个加载器的 load 方法, 加载资源。

p._loadNext = function() {
  if (this._paused) {
    return;
  }

  // Only dispatch loadstart event when the first file is loaded.
  if (!this._loadStartWasDispatched) {
    this._sendLoadStart();
    this._loadStartWasDispatched = true;
  }

  // The queue has completed.
  if (this._numItems == this._numItemsLoaded) {
    this.loaded = true;
    this._sendComplete();

    // Load the next queue, if it has been defined.
    if (this.next && this.next.load) {
      this.next.load();
    }
  } else {
    this.loaded = false;
  }

  // Must iterate forwards to load in the right order.
  for (var i = 0; i < this._loadQueue.length; i++) {
    if (this._currentLoads.length >= this._maxConnections) {
      break;
    }
    var loader = this._loadQueue[i];

    // Determine if we should be only loading one tag-script at a time:
    if (!this._canStartLoad(loader)) {
      continue;
    }
    this._loadQueue.splice(i, 1);
    i--;
    this._loadItem(loader);
  }
};

p._loadItem = function(loader) {
  loader.on("fileload", this._handleFileLoad, this);
  loader.on("progress", this._handleProgress, this);
  loader.on("complete", this._handleFileComplete, this);
  loader.on("error", this._handleError, this);
  loader.on("fileerror", this._handleFileError, this);
  this._currentLoads.push(loader);
  this._sendFileStart(loader.getItem());
  loader.load();
};
LoadQueue ( [preferXHR=true] [basePath=""] [crossOrigin=""] )

true 为使用 XHRLoader,false 将使用 TagLoader

LoadQueue的构造函数有三个参数,都是可选的:

1.preferXHR 这个表明是用XHR还是用HTML标签来加载。如果是false的时候,就用标签来加载,如果不能用标签的话,就还是用XHR来加载。默认是true,也就是说默认是用XHR来加载。

2.basePath 在加载资源时的,会把basePath加载url前面。这样加载同一个目录下的文件时,可以方便一点。 但是如果url是以协议(如”http://”)或者”../”这样路径开头时,不会添加basePath。

3.crossOrgin 这个参数不再用了,被LoadItem.crossOrigin取代了。

Creating a Queue

 var queue = new createjs.LoadQueue(true);

方法:

.loadFile ( file [loadNow=true] [basePath] )
参数说明:

file LoadItem | Object | String The file object or path to load. A file can be either

  • A LoadItem instance
  • An object containing properties defined by LoadItem
  • OR A string path to a resource. Note that this kind of load item will be converted to a LoadItem in the background.
queen.loadFile('/img/a.jpg');
queen.loadFile({
    src:'../img/a.jpg',
    type:'png', //一般是扩展名
    id:'img1',
    crossOrigin:true,
    mimeType:'text' //json/xml/text/css/js
});
.loadManifest ( manifest [loadNow=true] [basePath] )

一般是一个有多个item的数组作为第一个参数

.reset ()

Stops all open loads, destroys any loaded items, and resets the queue, so all items can be reloaded again by calling load. Items are not removed from the queue. To remove items use the remove or removeAll method.

.setPaused()
.setPreferXHR()
.setTag()
.setMaxConnections ( value )

The number of concurrent loads to allow. By default, only a single connection per LoadQueue is open at any time.

.load ()

Start a LoadQueue that was created, but not automatically started.

  1. 创建请求
  2. 每个请求绑定事件
  3. 执行所有请求
var queue = new createjs.LoadQueue();
queue.on("complete", handleComplete);
queue.loadManifest(fileArray, false); // Note the 2nd argument that tells the queue not to start loading yet
queue.load();
.getResult ( value [rawResult=false] )

Look up a loaded result using either the "id" or "src" that was specified when loading it. Note that if no "id" was supplied with the load item, the ID will be the "src", including a path property defined by a manifest. The basePath will not be part of the ID.

.getItem( value )

Look up a LoadItem using either the "id" or "src" that was specified when loading it. Note that if no "id" was supplied with the load item, the ID will be the "src", including a path property defined by a manifest. The basePath will not be part of the ID.

.getItems()

事件

.fileload(evt) //evt.result
.progress(evt) //evt.progress
.complete(evt)

思考

  1. 如何判断加载的类型?
queen.on('fileload',function (evt) {
  if (evt.item.type == "image") { images[evt.item.id] = evt.result; }
});
  1. 已加载百分比?
queen.on('progress',function (evt) {
  var progress = evt.progress;
  progress = progress > 1 ? 1 : progress;
  progress = Math.floor(progress*100);
});
  1. 根据扩展名获取Type值
s.getTypeByExtension = function(extension) {
  if (extension == null) {
    return createjs.Types.TEXT;
  }

  switch (extension.toLowerCase()) {
    case "jpeg":
    case "jpg":
    case "gif":
    case "png":
    case "webp":
    case "bmp":
      return createjs.Types.IMAGE;
    case "ogg":
    case "mp3":
    case "webm":
      return createjs.Types.SOUND;
    case "mp4":
    case "webm":
    case "ts":
      return createjs.Types.VIDEO;
    case "json":
      return createjs.Types.JSON;
    case "xml":
      return createjs.Types.XML;
    case "css":
      return createjs.Types.CSS;
    case "js":
      return createjs.Types.JAVASCRIPT;
    case 'svg':
      return createjs.Types.SVG;
    default:
      return createjs.Types.TEXT;
  }
};

4、 Types.js

var s ={};
s.BINARY = "binary";
s.CSS = "css";
s.FONT = "font";
s.FONTCSS = "fontcss";
s.IMAGE = "image";
s.JAVASCRIPT = "javascript";
s.JSON = "json";
s.JSONP = "jsonp";
s.MANIFEST = "manifest";
s.SOUND = "sound";
s.VIDEO = "video";
s.SPRITESHEET = "spritesheet";
s.SVG = "svg";
s.TEXT = "text";
s.XML = "xml";
  1. 如果item无id则自动生成id
// If there's no id, set one now.
var autoId = item.src;
if (item.id === undefined || item.id === null || item.id === "") {
  item.id = autoId;
}
  1. 创建loader
p._createLoader = function (item) {
  if (item._loader != null) { // A plugin already specified a loader
    return item._loader;
  }

  // Initially, try and use the provided/supported XHR mode:
  var preferXHR = this.preferXHR;

  for (var i = 0; i < this._availableLoaders.length; i++) {
    var loader = this._availableLoaders[i];
    if (loader && loader.canLoadItem(item)) {
      return new loader(item, preferXHR);
    }
  }

  // TODO: Log error (requires createjs.log)
  return null;
};
  1. 网络请求参考TagRequest,XHRRequest

  2. event解析

event.target//对应LoadQueue实例
event.type //
event.item //加载的item列表
event.rawResult //加载的文档中的内容
event.result //结果文档标签,可以直接解析
event.loader //指向加载器的实例
  1. 如何自己实现一个AssetManger?

Clone this wiki locally