组件代码
<template>
<view class="easy-loadimage" :id="uid">
<image class="origin-img" :src="imageSrc" :mode="mode" @click="ui.showImg(imageSrc)"
v-if="loadImg&&!isLoadError" v-show="showImg"
:class="{'no-transition':!openTransition,'show-transition':showTransition&&openTransition}"
@load="handleImgLoad" @error="handleImgError">
</image>
<view class="loadfail-img" v-else-if="isLoadError"></view>
<view :class="['loading-img',loadingMode]" v-show="!showImg&&!isLoadError"></view>
</view>
</template>
<script>
// 生成全局唯一id
function generateUUID() {// eslint-disable-line
// eslint-disable-next-line
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0 // eslint-disable-line
const v = c == 'x' ? r : (r & 0x3 | 0x8) // eslint-disable-line
return v.toString(16) // eslint-disable-line
})
}
export default {
props: {
imageSrc: {
type: String,
},
mode: {
type: String,
},
scrollTop: {
type: Number,
},
loadingMode: {
type: String,
default: 'looming-gray'
},
openTransition: {
type: Boolean,
default: true,
},
viewHeight: {
type: Number,
default() {
return uni.getSystemInfoSync().windowHeight
}
},
showAll: { // 是否显示全部图片
type: Boolean,
default: true,
required: false
},
},
watch: {
scrollTop(val) {
this.onScroll(val)
}
},
data() {
return {
uid: '',
loadImg: false,
showImg: false,
isLoadError: false,
showTransition: false,
}
},
methods: {
init() {
this.uid = 'uid-' + generateUUID()
this.$nextTick(this.onScroll)
},
handleImgLoad(e) {
this.showImg = true
setTimeout(() => {
this.showTransition = true
}, 50)
},
handleImgError(e) {
this.isLoadError = true
},
onScroll(scrollTop) {
// 加载ing时才执行滚动监听判断是否可加载
if (this.loadImg || this.isLoadError) return
const id = this.uid
const query = uni.createSelectorQuery().in(this)
query.select('#' + id).boundingClientRect(data => {
if (this.showAll) {
this.loadImg = true
} else {
if (!data) return
if (data.top - this.viewHeight < 0) {
this.loadImg = true
}
}
}).exec()
},
},
mounted() {
this.init()
}
}
</script>
<style scoped>
/* 官方优化图片tips */
image {
will-change: transform
}
/* 渐变过渡效果处理 */
image.origin-img {
opacity: 0.3;
}
image.origin-img.show-transition {
transition: opacity 1.2s;
opacity: 1;
}
image.origin-img.no-transition {
opacity: 1;
}
/* 加载失败、加载中的占位图样式控制 */
.loadfail-img {
height: 100%;
background: url('@/static/images/common/loadfail.png') no-repeat center;
background-size: 50%;
}
.loading-img {
height: 100%;
}
/* 转圈 */
.spin-circle {
background: url('@/static/images/common/loading1.gif') no-repeat center;
background-size: 100 rpx;
}
/* 动态灰色若隐若现 */
.looming-gray {
animation: looming-gray 1s infinite linear;
background-color: #e3e3e3;
}
@keyframes looming-gray {
0% {
background-color: #e3e3e3aa;
}
50% {
background-color: #e3e3e3;
}
100% {
background-color: #e3e3e3aa;
}
}
/* 骨架屏1 */
.skeleton-1 {
background-color: #e3e3e3;
background-image: linear-gradient(100deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0) 80%);
background-size: 100 rpx 100%;
background-repeat: repeat-y;
background-position: 0 0;
animation: skeleton-1 .6s infinite;
}
@keyframes skeleton-1 {
to {
background-position: 200% 0;
}
}
/* 骨架屏2 */
.skeleton-2 {
background-image: linear-gradient(-90deg, #fefefe 0%, #e6e6e6 50%, #fefefe 100%);
background-size: 400% 400%;
background-position: 0 0;
animation: skeleton-2 1.2s ease-in-out infinite;
}
@keyframes skeleton-2 {
to {
background-position: -135% 0;
}
}
</style>
调用方法示例
<template>
<view class="list">
<view class="item" v-for="(item,index) of list" :key="index">
<imgLoad mode="widthFix"
:scroll-top="scrollTop"
:image-src="item.image"></imgLoad >
<text>{{item.content}}</text>
</view>
</view>
</template>
export default{
data(){
return {
list:MockData, // 此处放自己的测试数据
scrollTop:0
}
},
onPageScroll({scrollTop}) {
// 传入scrollTop值并触发所有easy-loadimage组件下的滚动监听事件
this.scrollTop = scrollTop;
},
}
<style scoped>
.list{display: flex;justify-content: space-between;flex-wrap: wrap;padding: 32rpx;background: #F1F1F1;}
.list .item{width: 48%;background: #fff;margin-bottom: 80rpx;border-radius: 20rpx;}
.list .item >>> .easy-loadimage{
width: 100%;
/* height: 500rpx; */
margin-bottom: 38rpx;
}
.list .item >>> .origin-img{
border-radius: 20rpx;
}
/* mode为widthFix即图片高度自适应时要设置占位图默认高度 */
.list .item >>> .loadfail-img,.list .item >>>.loading-img{
height: 500rpx;
}
</style
属性名 | 类型 | 必填 | 默认值 | 说明 |
---|---|---|---|---|
image-src | String | 是 | 图片资源地址 | |
scroll-top | Number | 是 | 传入滚动值监听并触发组件 | |
mode | String | 否 | 同image组件的mode属性 | |
loading-mode | String | 否 | looming-gray | loading加载中的占位图效果 |
open-transition | Boolean | 否 | true | 是否开启加载成功后的渐现过渡效果 |
view-height | Number | 否 | 真机可视窗高度 | 可视区域高度 |
值 | 说明 |
---|---|
spin-circle | 转圈圈 |
looming-gray | 动态灰背景若隐若现 |
skeleton-1 | 骨架屏效果1 |
skeleton-2 | 骨架屏效果2 |
你也可以在以此类推在源码上修改或者扩展为你理想的样式
使用深度作用选择器>>>或在插件源码CSS部分上进行样式修改
类名 | 说明 |
---|---|
.easy-loadimage | 图片父元素 |
.origin-img | 源图片 |
.loading-img | 加载占位图 |
.loadfail-img | 加载失败占位图 |
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有