使用交叉点观察器延迟加载图像以提高性能

可以试试点击后方使用交叉点观察期延迟加载图像以提高性能链接阅读体验会更好

前言

在自己平时浏览一些大量图片类的网站时,你会发现无论是你pc端下拉滚动条,还是移动端手动滑屏时,最终呈现的图片有时候会有所延迟,这是一种预先加载图片资源的方式,也就是俗称懒加载,实现该效果,通常有两种方式,分别是线性式(下拉窗帘式的)和渐进式(拨开晨雾见日明)图片加载,

至于前者这里暂且不谈,本文主要是介绍后者,在本文中主要给img标签添加一data-src属性(实际图片URL),以及src属性(存储相同图像的非常小的分辨率路径图片),在加载图片时,给用户过度从模糊淡入到图片清晰.当然更重要的是其中的js处理.如果文有误导的地方,欢迎路过的老师多提意见和指正

图片占据了你网站大小的较高比例。其中一些图像位于下方,这意味着网站访问者不会立即看到你的网站。他们需要向下滚动才能查看图像。如果你只能显示立即查看的图像,然后预先加载折叠下的图像呢?是的你可以。这就是这篇文章的内容。某处你必须看到这样的功能在Medium上

考虑图像源

我们将在这篇文章中考虑的例子将包含5张或更多图片,但每个图片都会有这种结构

目录

  1. 考虑图像源(data-src,与src)
  2. 观察员(创建实例并使用此实例观察DOM元素)
  3. 处理交叉路口(条目存储所有匹配的DOM元素,调用loadImage获取图像,然后适当地设置图像的src)
  4. 其他考虑事项(模糊转换为清晰时,为图像添加淡入效果)
  5. 结论(使用渐进式图片,你可以减少用户资源浪费大量时间来下载内容)

代码:

<img src="http://res.cloudinary.com/christekh/image/upload/c_scale,h_3,w_5/v1505391130/wynand-van-poortvliet-364366_gsvyby.jpg" data-src="http://res.cloudinary.com/christekh/image/upload/c_scale,h_300,w_500/v1505391130/wynand-van-poortvliet-364366_gsvyby.jpg" >

每个标签都有一个data-src和一个src属性

  1. data-src是我们希望读者看到的图像的实际URL(宽度:500px)
  2. src包含相同图像的非常小的分辨率(宽度:5px)。这个分辨率将被拉伸以填充空间并且在真实图像加载时给访问者模糊的效果。较小的图像比其小10倍,所以如果所有条件都正常,则会加载速度更快(10倍)

这些图像存储在Cloudinary服务器上,可以通过URL(h_300,w_500或h_3,w_5)轻松调整图像的尺寸

这是完整的HTML代码示例

<div class="container">
        <!-- Image 1 -->
        <img src="" data-src="" alt="">
        <!-- Image 2 -->
        <img src="" data-src="" alt="">
        <!-- Image 3 -->
        <img src="" data-src="" alt="">
        <!-- Image 4 -->
        <img src="" data-src="" alt="">
        <!-- Image 5 -->
        <img src="" data-src="" alt="">
</div>

观察员

这是完整的js代码:

/**
 * 
 * @authors 随笔川迹 (itclanCode@163.com)
 * @date    2018-03-19 00:58:29
 * @version $Id$
 * @weChatPublicId ((itclanCoder))
 * @QQGroup ((643468880))
 * @PersonWeChatId ((suibichuanji))
 * @PersonQQ ((1046678249))
 * @link ((https://juejin.im/post/5a005392518825295f5d53c8))
 * @describe 使用交叉点观察器延迟加载图像以提高性能js代码
 */
// 获取img标签元素
const images = document.querySelectorAll('img');

// 选项options
const options = {
  // 如果图像在Y轴上达到50像素以内,请开始下载 If the image gets within 50px in the Y axis, start the download.
  root: null, // 以页面作为根元素 Page as root
  rootMargin: '0px',
  threshold: 0.1
};
// 取得图片
const fetchImage = (url) => {
  console.log(url);
  return new Promise((resolve, reject) => {
    const image = new Image();
    image.src = url;
    image.onload = resolve;
    image.onerror = reject;
  });
}
// 加载图片
const loadImage = (image) => {
  const src = image.dataset.src;
  fetchImage(src).then(() => {
    // console.log(src)
    image.src = src;
  })
}
// 处理交叉路口,entries代表条目,observer观察者
const handleIntersection = (entries, observer) => {
  entries.forEach(entry => {
    if(entry.intersectionRatio > 0) {
      console.log(entry.intersectionRatio);
      loadImage(entry.target)
    }
  })
}

// 页面上图像的观察者 The observer for the images on the page
const observer = new IntersectionObserver(handleIntersection, options);

images.forEach(img => {
  observer.observe(img);
})

观察者是交集观察者的一个实例。你创建实例并使用此实例观察DOM元素。你可以观察元素何时进入视口

   const options = {
      rootMargin:'0px',
      threshold:0.1
   }
   const observer = new IntersectionObserver(handleIntersection,options);

该实例需要一个处理程序和一个选项参数。处理程序是当匹配交叉点发生时调用的函数,而options参数定义了观察者的行为。在这种情况下,我们希望处理器在图像进入视口后立即被调用(阈值:0.1)

你可以使用观察者观察页面中的所有图像

   const images = document.querySelectorAll('img');
   images.forEach(img => {
       observer.observe(img);
    })

处理交叉路口

我们为处理程序使用了一个方法,但没有定义它。这将会像预期的那样尖叫一个错误。让我们在实例上创建处理程序

    const handleIntersection = (entries,observer) =>{
        entries.forEach(entry =>{
            if(entry.intersectionRatio > 0){
                loadImage(entry.target);
            }
        }

        )
    }

该方法由带有条目数组和观察者实例的API调用。条目存储所有匹配的DOM元素(在这种情况下为imgs)的一个实例。如果匹配,我们用元素调用loadImage

loadImage获取图像,然后适当地设置图像的src

   const loadImage = (image) => {
      const src = image.dataset.src;
      fetchImage(src).then(() => {
         image.src = src;
      })
   }

它通过使用data-src值调用fetchImage方法来完成此操作。当实际图像返回时,它会设置image.src的值

fetchImage获取图像并返回一个承诺

    const fetchImage = (url) => {
        return new Promise((resolve,reject) => {
           const image = new Image();
           img.src = url;
           image.onload = resolve;
           image.onerror = reject;
        })
    }

其他考虑事项

考虑到流畅的用户体验,当从模糊转换为清晰时,你还可以为图像添加淡入效果。如果观看者认为加载时间较慢,这使得它更吸引眼睛

请注意,Intersection Observer在所有浏览器中都不被广泛支持,因此你可能会考虑使用填充或在页面加载后自动加载图像

   if('IntersectionObserver' in window){
      // observer code
      const observer = new IntersectionObserver(handleIntersection,options);
   }else{
       Array.from(images).forEach(image => loadImage(image))
   }

结论

使用渐进式图片,你可以减少用户资源浪费大量时间来下载内容,其实也就是预先加载资源更小的资源,策略就是减少文件的体积,循序渐进的加载,减少带宽,从而提高页面的访问速度,这在面试当中不妨也是一种优化页面性能的答复,当然还有其他?若知后文,关注微信itclanCoder公众号即可,下一篇内容继续揭晓...

原文链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 星月相辉映, 银霜似朦胧。 独坐屋檐下, 温酒也寒冷。
    序小木阅读 169评论 15 15
  • 周六,艳阳高照。起的很早,却不知所措。麻木的心不知所以,内心潜伏着的压力无处安放。时常感到迷茫无知,想探索未来,却...
    白鹤清阅读 592评论 1 3
  • 最开始是因为《屌丝男士》的大火才知道他,大鹏,东北人,一个超级搞笑又接地气儿的屌丝。印象中的他总是乐观的。 昨天观...
    妆文青阅读 351评论 4 6
  • “油炸知了猴,油炸蚂蚱”每到菜市场听到这一声吆喝,我都感觉特别亲切。有时买来尝尝,浓浓的油炸味遮住了食物本身的香,...
    杨帆沧州阅读 349评论 1 3