图片渐进式加载
渐进式加载是指图片在加载过程中由模糊到清晰的一个加载过程,需要两张图片实现,一张体积比较小,一张为原图,体积比较小的图片会先加载成功,然后对其进行模糊化处理,直到原图加载成功后,用原图替代体积较小的图。
css filter模糊处理:
- html
<div class="placeholder" data-large="https://pic2.zhimg.com/50/v2-c5174d0b98facea9584e7766862decdd_400x224.jpg">
<img src="https://pic2.zhimg.com/50/v2-c5174d0b98facea9584e7766862decdd_60w.jpg" class="img-small">
<div style="padding-bottom: 66.6%;"></div>
</div>
- css
.placeholder {
width: 200px;
background-color: #f6f6f6;
background-size: cover;
background-repeat: no-repeat;
position: relative;
overflow: hidden;
}
.placeholder img {
position: absolute;
opacity: 0;
top: 0;
left: 0;
width: 100%;
transition: opacity 1s linear;
}
.placeholder img.loaded {
opacity: 1;
}
.img-small {
filter: blur(50px);
/* this is needed so Safari keeps sharp edges */
transform: scale(1);
}
- js
window.onload = function () {
var placeholder = document.querySelector('.placeholder'),
small = placeholder.querySelector('.img-small')
// 1: load small image and show it
var img = new Image();
img.src = small.src;
img.onload = function () {
small.classList.add('loaded');
};
// 2: load large image
var imgLarge = new Image();
imgLarge.src = placeholder.dataset.large;
imgLarge.onload = function () {
// small.classList.remove('loaded');
imgLarge.classList.add('loaded');
};
placeholder.appendChild(imgLarge);
}
canvas模糊处理:
- html
<div class="figure">
<div class="aspect-ratio-fill"></div>
<img id="smallImg" class="small-img" crossorigin="anonymous" src="https://pic2.zhimg.com/50/v2-c5174d0b98facea9584e7766862decdd_60w.jpg"
alt="">
<canvas id="canvas" class="canvas"></canvas>
<img class="big-img" data-src="https://pic2.zhimg.com/50/v2-c5174d0b98facea9584e7766862decdd_400x224.jpg">
</div>
- css
.figure {
position: relative;
width: 200px;
overflow: hidden;
}
.aspect-ratio-fill {
padding-bottom: 66.67%;
}
.figure img,
.figure canvas {
position: absolute;
top: 0;
left: 0;
width: 100% !important;
height: 100% !important;
opacity: 1;
transition: opacity 2s linear;
}
.canvas.loaded {
opacity: 0;
}
.small-img {
display: none;
}
- js
let smallImg = document.querySelector('.small-img'),
canvas = document.querySelector('.canvas'),
bigImg = document.querySelector('.big-img');
ctx = canvas.getContext('2d');
smallImg.onload = function () {
StackBlur.image(smallImg, canvas, 20, true);
if (bigImg.getBoundingClientRect().top > 0 && bigImg.getBoundingClientRect().bottom < window.innerHeight) {
bigImg.setAttribute('src', bigImg.dataset.src);
bigImg.onload = function () {
canvas.classList.add('loaded');
}
}
}
参考文献:
[1] How Medium does progressive image loading