未进入窗口的图片资源,展示骨架屏动画
#IntersectionObserver #骨架屏动画
实现
template 模板
<template>
<!-- 懒加载 -->
<div class="lazy-load" :class="{ loading: isLoad }" ref="lazyLoad">
<img src="" alt="" srcset="" />
</div>
</template>
js 部分
这里主要使用IntersectionObserver api 传入一个callback 接收一个数组对象。
当页面滚动时候,自动调用callback,我们可以判断对象的isIntersecting 属性。
当为true时,src 地址赋值给图片,并在加载完成的时候是骨架屏动画消失。
export default {
name: "lazyLoad",
props: {
src: {
type: String,
default: "",
},
},
data() {
return {
isLoad: true, // 图片状态
};
},
mounted() {
let node = this.$refs["lazyLoad"]; // 获取节点
let observer = new IntersectionObserver((entries) => {
//是否进入视野
let flag = entries.some(entry =>entry.isIntersecting);
if (flag) {
// 图片加载
let img = node.querySelector("img");
img.src = this.src;
img.onload = () => {
this.isLoad = false; // 骨架屏动画消失
};
// 停止观察
observer.disconnect();
}
});
observer.observe(node);
},
};
scss 部分
/* 骨架屏动画 */
@keyframes skeleton-ani {
from {
left: -100%;
}
to {
left: 150%;
}
}
.lazy-load {
// width: 100%;
min-height: 60px;
display: block;
img {
// width: auto;
flex: 1;
width: 100%;
}
// 加载效果
&.loading {
pointer-events: none;
position: relative;
background-color: #ccc;
overflow: hidden;
&::after {
position: absolute;
top: 0;
width: 30%;
height: 100%;
content: "";
background: linear-gradient(
to right,
rgba(255, 255, 255, 0) 0,
rgba(255, 255, 255, 0.3) 50%,
rgba(255, 255, 255, 0.3) 70%,
rgba(255, 255, 255, 0) 100%
);
transform: skewX(-45deg);
z-index: 99;
animation: skeleton-ani 1s ease infinite;
display: block;
}
}
}
使用
<template>
<div>
<lazy-load src="http://192.168.100.101:5500/img?name=cat"></lazy-load>
</div>
</template>
<script>
import lazyLoad from "./lazyLoad.vue";
export default {
components: {
lazyLoad,
},
}
</script>