Rumah  >  Artikel  >  hujung hadapan web  >  Memahami kemahiran pramuat_javascript imej Javascript

Memahami kemahiran pramuat_javascript imej Javascript

WBOY
WBOYasal
2016-05-16 15:13:591065semak imbas

Pramuat imej ialah cara terbaik untuk meningkatkan pengalaman pengguna. Dengan imej yang dipramuat ke dalam penyemak imbas, pelawat boleh melayari tapak anda dengan lancar dan menikmati masa pemuatan yang sangat pantas. Ini sangat berfaedah untuk galeri imej dan tapak web di mana imej mengambil bahagian yang besar Ia memastikan imej diterbitkan dengan cepat dan lancar, dan ia juga membantu pengguna mendapatkan pengalaman pengguna yang lebih baik apabila menyemak imbas kandungan tapak web anda. Artikel ini akan berkongsi tiga teknik pramuat yang berbeza untuk meningkatkan prestasi dan kebolehgunaan tapak web.

Kaedah 1: Gunakan CSS dan JavaScript untuk melaksanakan pramuat

Terdapat banyak cara untuk melaksanakan imej pramuat, termasuk menggunakan CSS, JavaScript dan pelbagai kombinasi kedua-duanya. Teknologi ini boleh mereka bentuk penyelesaian yang sepadan mengikut senario reka bentuk yang berbeza dan sangat cekap.

Hanya gunakan CSS untuk pramuat imej dengan mudah dan cekap Kodnya adalah seperti berikut:

#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }
#preload-02 { background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }
#preload-03 { background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; } 

Menggunakan tiga pemilih ID ini pada elemen HTML (X), kami boleh pramuat imej ke latar belakang luar skrin melalui atribut latar belakang CSS. Selagi laluan ke imej ini kekal sama, penyemak imbas akan menggunakan imej yang dipramuat (cache) semasa proses pemaparan apabila ia dipanggil di tempat lain pada halaman web. Mudah, cekap dan tidak memerlukan sebarang JavaScript.

Walaupun kaedah ini cekap, masih ada ruang untuk penambahbaikan. Imej yang dimuatkan menggunakan kaedah ini akan dimuatkan bersama-sama dengan kandungan lain pada halaman, meningkatkan masa pemuatan keseluruhan halaman. Untuk menyelesaikan masalah ini, kami menambahkan beberapa kod JavaScript untuk menangguhkan masa pramuat sehingga halaman dimuatkan. Kodnya adalah seperti berikut:

function preloader() {
  if (document.getElementById) {
    document.getElementById("preload-01").style.background = "url(http://domain.tld/image-01.png) no-repeat -9999px -9999px";
    document.getElementById("preload-02").style.background = "url(http://domain.tld/image-02.png) no-repeat -9999px -9999px";
    document.getElementById("preload-03").style.background = "url(http://domain.tld/image-03.png) no-repeat -9999px -9999px";
  }
}
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}
addLoadEvent(preloader);

Dalam bahagian pertama skrip, kami mendapatkan elemen menggunakan pemilih kelas dan menetapkan atribut latar belakang padanya untuk pramuat imej yang berbeza.

Dalam bahagian kedua skrip, kami menggunakan fungsi addLoadEvent() untuk menangguhkan masa pemuatan fungsi preloader() sehingga halaman dimuatkan.

Apakah yang berlaku jika JavaScript tidak berjalan dengan betul dalam penyemak imbas pengguna? Ia sangat mudah. ​​Imej tidak akan dimuatkan apabila halaman memanggil imej, ia akan dipaparkan seperti biasa.

Kaedah 2: Gunakan JavaScript sahaja untuk melaksanakan pramuat

Kaedah di atas kadangkala sangat cekap, tetapi kami secara beransur-ansur mendapati bahawa ia akan mengambil terlalu banyak masa dalam proses pelaksanaan sebenar. Sebaliknya, saya lebih suka menggunakan JavaScript tulen untuk pramuat imej. Di bawah ialah dua kaedah pramuat sedemikian yang berfungsi dengan baik pada semua penyemak imbas moden.

coretan kod JavaScript 1

Anda hanya perlu mengedit dan memuatkan laluan dan nama imej yang diperlukan. Ia mudah untuk dilaksanakan:

<div class="hidden">
  <script type="text/javascript">
      var images = new Array()
      function preload() {
        for (i = 0; i < preload.arguments.length; i++) {
          images[i] = new Image()
          images[i].src = preload.arguments[i]
        }
      }
      preload(
        "http://domain.tld/gallery/image-001.jpg",
        "http://domain.tld/gallery/image-002.jpg",
        "http://domain.tld/gallery/image-003.jpg"
      )
  </script>
</div>

Kaedah ini amat sesuai untuk pramuat sejumlah besar imej. Laman web galeri saya menggunakan teknologi ini untuk pramuat lebih 50 imej. Gunakan skrip ini pada halaman log masuk dan kebanyakan imej galeri akan dipramuat sebaik sahaja pengguna memasukkan ID log masuk mereka.

coretan kod JavaScript 2

Kaedah ini serupa dengan kaedah di atas dan juga boleh pramuat sebarang bilangan imej. Tambahkan skrip berikut pada mana-mana halaman Web dan editnya mengikut arahan program.

<div class="hidden">
  <script type="text/javascript">
      if (document.images) {
        img1 = new Image();
        img2 = new Image();
        img3 = new Image();
        img1.src = "http://domain.tld/path/to/image-001.gif";
        img2.src = "http://domain.tld/path/to/image-002.gif";
        img3.src = "http://domain.tld/path/to/image-003.gif";
      }
  </script>
</div>
 

Seperti yang anda lihat, setiap kali anda memuatkan imej, anda perlu mencipta pembolehubah, seperti "img1 = new Image();", dan mengisytiharkan alamat sumber imej, seperti "img3.src = ". ./path/to/image- 003.gif";". Menggunakan corak ini, anda boleh memuatkan seberapa banyak imej yang anda perlukan.

Kami telah menambah baik kaedah ini sekali lagi. Balut skrip ini ke dalam fungsi dan gunakan addLoadEvent() untuk menangguhkan masa pramuat sehingga halaman dimuatkan.

function preloader() {
  if (document.images) {
    var img1 = new Image();
    var img2 = new Image();
    var img3 = new Image();
    img1.src = "http://domain.tld/path/to/image-001.gif";
    img2.src = "http://domain.tld/path/to/image-002.gif";
    img3.src = "http://domain.tld/path/to/image-003.gif";
  }
}
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}
addLoadEvent(preloader);

Kaedah 3: Gunakan Ajax untuk melaksanakan pramuat

Kaedah yang diberikan di atas nampaknya tidak cukup hebat, jadi sekarang mari kita lihat kaedah menggunakan Ajax untuk melaksanakan pramuat imej. Kaedah ini menggunakan DOM untuk bukan sahaja pramuat imej, tetapi juga pramuat CSS, JavaScript dan perkara lain yang berkaitan. Kelebihan menggunakan Ajax berbanding menggunakan JavaScript secara langsung ialah pemuatan JavaScript dan CSS tidak akan menjejaskan halaman semasa. Kaedahnya mudah dan berkesan.

window.onload = function() {
  setTimeout(function() {
    // XHR to request a JS and a CSS
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://domain.tld/preload.js');
    xhr.send('');
    xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://domain.tld/preload.css');
    xhr.send('');
    // preload image
    new Image().src = "http://domain.tld/preload.png";
  }, 1000);
};

Kod di atas pramuat "pramuat.js", "pramuat.css" dan "pramuat.png". Tamat masa 1000 milisaat adalah untuk mengelakkan skrip daripada digantung dan menyebabkan masalah fungsi dengan halaman biasa.

Seterusnya, mari lihat cara menggunakan JavaScript untuk melaksanakan proses pemuatan:

window.onload = function() {
 
  setTimeout(function() {
 
    // reference to <head>
    var head = document.getElementsByTagName('head')[0];
 
    // a new CSS
    var css = document.createElement('link');
    css.type = "text/css";
    css.rel = "stylesheet";
    css.href = "http://domain.tld/preload.css";
 
    // a new JS
    var js = document.createElement("script");
    js.type = "text/javascript";
    js.src = "http://domain.tld/preload.js";
 
    // preload JS and CSS
    head.appendChild(css);
    head.appendChild(js);
 
    // preload image
    new Image().src = "http://domain.tld/preload.png";
 
  }, 1000);
 
};

Di sini, kami mencipta tiga elemen melalui DOM untuk pramuat tiga fail. Seperti yang dinyatakan di atas, dengan Ajax, memuatkan fail tidak digunakan pada halaman memuatkan. Dari sudut pandangan ini, kaedah Ajax lebih unggul daripada JavaScript.

Maklumat tambahan: Memuatkan fungsi panggil balik penyelesaian

Kami menulis kod berikut:

function loadImage(url, callback) {
 var img = new Image();
 img.src = url;

 img.onload = function(){ //图片下载完毕时异步调用callback函数。
  callback.call(img);  // 将callback函数this指针切换为img。
 };
}

在firefox中测试一下,发现不错,果然和预想的效果一样,在图片下载后,就会弹出图片的宽度来。无论点击多少次或者刷新结果都一样。

不过,做到这一步,先别高兴太早——还需要考虑一下浏览器的兼容性,于是,赶紧到ie里边测试一下。没错,同样弹出了图片的宽度。但是,再点击load的时候,情况就不一样了,什么反应都没有了。刷新一下,也同样如此。

经过对多个浏览器版本的测试,发现ie6、opera都会这样,而firefox和safari则表现正常。其实,原因也挺简单的,就是因为浏览器的缓存 了。当图片加载过一次以后,如果再有对该图片的请求时,由于浏览器已经缓存住这张图片了,不会再发起一次新的请求,而是直接从缓存中加载过来。对于 firefox和safari,它们视图使这两种加载方式对用户透明,同样会引起图片的onload事件,而ie和opera则忽略了这种同一性,不会引 起图片的onload事件,因此上边的代码在它们里边不能得以实现效果。

怎么办呢?最好的情况是Image可以有一个状态值表明它是否已经载入成功了。从缓存加载的时候,因为不需要等待,这个状态值就直接是表明已经下载了,而从http请求加载时,因为需要等待下载,这个值显示为未完成。这样的话,就可以搞定了。

经过一些分析,终于发现一个为各个浏览器所兼容的Image的属性——complete。所以,在图片onload事件之前先对这个值做一下判断即可。最后,代码变成如下的样子:

function loadImage(url, callback) {
  var img = new Image(); //创建一个Image对象,实现图片的预下载
  img.src = url;
  
  if (img.complete) { // 如果图片已经存在于浏览器缓存,直接调用回调函数
    callback.call(img);
    return; // 直接返回,不用再处理onload事件
  }

  img.onload = function () { //图片下载完毕时异步调用callback函数。
    callback.call(img);//将回调函数的this替换为Image对象
  };
};

虽然代码很简单,但却很实用。 

附:再谈javascript图片预加载

lightbox类效果为了让图片居中显示而使用预加载,需要等待完全加载完毕才能显示,体验不佳(如filick相册的全屏效果)。javascript无法获取img文件头数据,真的是这样吗?本文通过一个巧妙的方法让javascript获取它。

这是大部分人使用预加载获取图片大小的例子:

var imgLoad = function (url, callback) {
  var img = new Image();

  img.src = url;
  if (img.complete) {
    callback(img.width, img.height);
  } else {
    img.onload = function () {
      callback(img.width, img.height);
      img.onload = null;
    };
  };

};
可以看到

上面必须等待图片加载完毕才能获取尺寸,其速度不敢恭维,我们需要改进。

web应用程序区别于桌面应用程序,响应速度才是最好的用户体验。如果想要速度与优雅兼得,那就必须提前获得图片尺寸,如何在图片没有加载完毕就能获取图片尺寸?

十多年的上网经验告诉我:浏览器在加载图片的时候你会看到图片会先占用一块地然后才慢慢加载完毕,并且不需要预设width与height属性,因为浏览器能够获取图片的头部数据。基于此,只需要使用javascript定时侦测图片的尺寸状态便可得知图片尺寸就绪的状态。

当然实际中会有一些兼容陷阱,如width与height检测各个浏览器的不一致,还有webkit new Image()建立的图片会受以处在加载进程中同url图片影响,经过反复测试后的最佳处理方式:

// 更新:
// 05.27: 1、保证回调执行顺序:error > ready > load;2、回调函数this指向img本身
// 04-02: 1、增加图片完全加载后的回调 2、提高性能

/**
 * 图片头数据加载就绪事件 - 更快获取图片尺寸
 * @version  2011.05.27
 * @author  TangBin
 * @see    http://www.planeart.cn/&#63;p=1121
 * @param  {String}  图片路径
 * @param  {Function}  尺寸就绪
 * @param  {Function}  加载完毕 (可选)
 * @param  {Function}  加载错误 (可选)
 * @example imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
    alert('size ready: width=' + this.width + '; height=' + this.height);
  });
 */
var imgReady = (function () {
  var list = [], intervalId = null,

  // 用来执行队列
  tick = function () {
    var i = 0;
    for (; i < list.length; i++) {
      list[i].end &#63; list.splice(i--, 1) : list[i]();
    };
    !list.length && stop();
  },

  // 停止所有定时器队列
  stop = function () {
    clearInterval(intervalId);
    intervalId = null;
  };

  return function (url, ready, load, error) {
    var onready, width, height, newWidth, newHeight,
      img = new Image();
    
    img.src = url;

    // 如果图片被缓存,则直接返回缓存数据
    if (img.complete) {
      ready.call(img);
      load && load.call(img);
      return;
    };
    
    width = img.width;
    height = img.height;
    
    // 加载错误后的事件
    img.onerror = function () {
      error && error.call(img);
      onready.end = true;
      img = img.onload = img.onerror = null;
    };
    
    // 图片尺寸就绪
    onready = function () {
      newWidth = img.width;
      newHeight = img.height;
      if (newWidth !== width || newHeight !== height ||
        // 如果图片已经在其他地方加载可使用面积检测
        newWidth * newHeight > 1024
      ) {
        ready.call(img);
        onready.end = true;
      };
    };
    onready();
    
    // 完全加载完毕的事件
    img.onload = function () {
      // onload在定时器时间差范围内可能比onready快
      // 这里进行检查并保证onready优先执行
      !onready.end && onready();
    
      load && load.call(img);
      
      // IE gif动画会循环执行onload,置空onload即可
      img = img.onload = img.onerror = null;
    };

    // 加入队列中定期执行
    if (!onready.end) {
      list.push(onready);
      // 无论何时只允许出现一个定时器,减少浏览器性能损耗
      if (intervalId === null) intervalId = setInterval(tick, 40);
    };
  };
})();

调用例子:

imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
  alert('size ready: width=' + this.width + '; height=' + this.height);
});

是不是很简单?这样的方式获取摄影级别照片尺寸的速度往往是onload方式的几十多倍,而对于web普通(800×600内)浏览级别的图片能达到秒杀效果。

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn