Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端之图片加载与渲染 #19

Open
jyzwf opened this issue Aug 2, 2017 · 0 comments
Open

前端之图片加载与渲染 #19

jyzwf opened this issue Aug 2, 2017 · 0 comments

Comments

@jyzwf
Copy link
Owner

jyzwf commented Aug 2, 2017

本文阅读收获于 Web图片资源的加载与渲染时机,感谢作者。

浏览器工作流程
ovyhw

图片加载和渲染时机:

  • 解析 HTML 【遇到 img 标签时加载图片】-->构建DOM树
  • 加载样式 --> 解析样式【遇到背景图片链接不加载】 -->构建样式规则树
  • 加载 js -->执行 js
  • 把 DOM 树和样式规则树匹配构建渲染树 【加上渲染树上的背景图片】
  • 计算元素位置进行布局
  • 绘制【开始渲染图片】

图片加载与渲染规则

display:none

<style>
        .bg-img {
             display: none; 
            background: url(../assets/imgs/process-of-browserlove.jpg)
        }
</style>

<body>
     <img src="../assets/imgs/process-of-browser.png" alt=""> 
    <div class="bg-img"></div>
</body>

image

  • 过程:设置该属性的元素,图片会加载,但不会渲染
  • 原理:把 DOM 树和样式规则树匹配构建渲染树时,会把 可渲染元素 上的所有属性(如:display:none / background-image)结合一起产出到渲染树。

当解析渲染树时会加载 img 标签上的图片,发现元素上有 background-image 属性时会加载背景图片

当绘制时发现元素上有 display:none 时,不计算该元素的位置,也不会绘制该元素

<style>
        .bg-img {
            background: url(../assets/imgs/love.jpg)
        }
</style>

<div style='display:none'>
        <img src="../assets/imgs/process-of-browser.png" alt="">
        <div class="bg-img"></div>
</div>

image

  • 过程:设置了display : none 属性的子元素,样式表中的背景图不会渲染出来,也不会加载;而 img 标签的图片不会渲染,但会加载
  • 原理:构建渲染树时,只会把 可渲染的元素产出到渲染树,这就是说,当匹配 DOM 树和样式规则树时,如果发现一个元素的属性上有 display:none,浏览器就会认为该元素是不可渲染的,所以不会把该元素的子元素产出到渲染树
    当解析和绘制渲染树时,由于没有设置了 display:none 属性的子元素,因此该元素的子元素背景图不会被加载和渲染
    <style>
        .bg-img {
            width: 400px;
            height: 400px;
            background-size: cover;
        }
</style>

<body>
    <div class="bg-img"></div>

    <script>
        var div = document.querySelector('div');
        div.style.display = 'none';
        div.style.background = 'url(../assets/imgs/love.jpg)';
    </script>
</body>

image

<style>
        .bg-img {
            width: 400px;
            height: 400px;
            background-size: cover;
        }
</style>

<div style="display:none">
        <div class="bg-img"></div>
    </div>


    <script>
        var div = document.querySelector('.bg-img');
        div.style.background = 'url(../assets/imgs/love.jpg)';
    </script>

image

重复图片

浏览器请求资源时,先判断是否有缓存,如有,且未过期的,则会从缓存中读取,不再请求。反之,先加载的图片会存储到浏览器的缓存中,以便后期获取

伪类的背景图片

<style>
        .bg-img {
            width: 400px;
            height: 400px;
            background: url(../assets/imgs/love.jpg)
        }

        .bg-img:hover {
            background: url(../assets/imgs/process-of-browser.png)
        }
</style>

<div class="bg-img"></div>

hover 前:
image

hover 后:
image

  • 过程:在触发伪类的时候才会去加载。
  • 原理:触发hover前,DOM 树与样式规则树匹配的是无 hover状态选择器 .bg-img 样式,因此渲染树上 background: url(../assets/imgs/love.jpg);生效,解析渲染树时加载的是 love.jpg,绘制时渲染的也是love.jpg。
    触发hover后,因为 .bg-img:hover 的优先级比较高,因此 DOM 树与样式规则树匹配的是有 hover 状态选择器 .bg-img:hover 的样式,渲染树上 background: url(../assets/imgs/process-of-browser.png); 生效,解析渲染树时加载的是 process-of-browser.png,绘制时渲染的也是 process-of-browser.png

应用

占位图

当使用样式表中的背景图片作为占位符时,要把背景图片转为 base64 格式。这是因为背景图片加载的顺序在标签后面,背景图片可能会在 标签图片加载完成后才开始加载,达不到想要的效果。

预加载

很多场景里图片是在改变或触发状态后才显示出来的,例如点击一个Tab后,一个设置display:none隐藏的父元素变为显示,这个父元素里的子元素图片会在父元素显示后才开始加载;又如当鼠标hover到图标后,改变图标图片,图片会在hover上去后才开始加载,导致出现闪一下这种不友好的体验。

解决:

  1. 若是小图标,可以合并成雪碧图,在改变状态前就把所有图标都一起加载了。
  2. 使用上文讲到的,设置了display:none属性的元素,图片不会渲染出来,但会加载。把要预加载的图片加到设置了display:none的元素背景图或标签里。
  3. 在 javascript 创建 img 对象,把图片 url 设置到 img 对象的 src 属性里。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant