如何优化网站性能,焦作网站建设哪家好,网站建设的教材,自动做图在线网站前言
这次的标题有点长#xff0c;主要是想要表述的功能点有点多#xff1b;
简单做一下需求描述
产品要求在商品详情页的头部轮播图部分#xff0c;可以单击预览大图#xff0c;同时在预览界面可以双指放大缩小图片并且可以移动查看图片#xff0c;双击放大#xff0…前言
这次的标题有点长主要是想要表述的功能点有点多
简单做一下需求描述
产品要求在商品详情页的头部轮播图部分可以单击预览大图同时在预览界面可以双指放大缩小图片并且可以移动查看图片双击放大单击还原左右滑动可以切换预览的图片非放大情况下单击退出预览类似于淘宝现在的商详图片预览要求微信小程序和H5中都实现该功能时间1.5天
需求分析
轮播图片点击唤起预览界面这部分功能已经很早实现了不做过多的解释界面中可以定制别的内容预览图片双指缩放预览图片放大之后可以拖动查看图片双击放大单击还原滑动切换图片单击关闭预览图片同时索引定位到预览的位置
简单思路
图片点击预览图片这个功能是之前就有的这次其实是加入了放大缩小手势等想着直接用uni-app的uni.previewImage它支持图片预览双击放大拖动轮播而且底层是native的性能很棒很丝滑不支持关闭预览定位索引不支持预览界面定制别的内容因此没办法直接放弃了
于是打算原生手写一个尝试之后发现H5能用但是很卡顿小程序没法看
最后想到了可以用uni-app的movable-area和movable-view开发一个可以拖动的区域配合swiper就可以了正好看了一下uni.previewImage的实现源码发现在H5端也是用这几个组件实现的源码位置于是决定参照源码开发一下
代码
div :class[img-preview, modal ? slide-down-to-up-opacity : slide-up-to-down-opacity]swiper classswiper-container :currentcurrent :disable-touchdisableTouch changehandleChangeSlideswiper-item v-for(img, idx) in picList :keyidx :class{swiper-slide: true}movable-area scale-area classmovable-areamovable-viewdirectionall:animationfalse:scale-min1:scale-max2:damping30:scale-valueimg.scale:scaletrue:inertiafalse:out-of-boundsfalse:class{movable-view:true}touchmovehandleTouchmove($event, idx)click.stophandleMovableClick($event, idx)scale.stophandleOnScale($event, idx)img:keyaward ? img.productImageSpecial : img.picture:srcaward ? img.productImageSpecial : img.picturemodewidthFix:class{preview-img: true}//movable-view/movable-area /swiper-item/swiperdiv v-ifpicList picList.length 1 classproduct-align-singlediv classproduct-align-dotsdiv v-for(item, idx) in picList :keyidx :class{product-align-dot: true, product-align-dot-active: idx current}/div/div/div/divexport default {name: ImgPreview,props: {// 显示与隐藏value: {type: Boolean,value: false},imgList: {type: Array,default() {return []}},initIndex: {type: Number,default: 0},fullscreen: {type: Boolean,default: true},award: {type: Boolean,default: false}},emits:[close,change-slide],data () {return {modal: this.value,current: this.initIndex,arrowIcon: https://static1.keepcdn.com/infra-cms/2023/3/7/17/35/553246736447566b58312f38753731477849327742542f44796c385238397273617968664475477a4f6c4d3d/48x48_e33efe885c6a5df9403962315de3681bad220cd2.png,scale: 1,lastTapTime: 0, // 记录上一次点击时间clickTimer: null,clickDelay: 300,disableTouch: false,picList: []}},watch: {value: {handler(val) {this.modal valif (val) {this.picList []this.imgList.forEach(item {this.picList.push({...item,scale: 1})})}},immediate:true},},methods: {handleOnScale(event, index) {const { scale, x, y } event.detaillet item this.picList[index]item.scale scalethis.$set(this.picList, index, item)this.$forceUpdate()},handleTouchmove(event, index) {this.disableTouch truelet item this.picList[index]if (item.scale ! 1) {this.disableTouch true} else {this.disableTouch false}},handleMovableClick(e, index) {console.log(e, )// 判断双击事件let curTime e.timeStampif (this.lastTapTime 0) {if (curTime - this.lastTapTime this.clickDelay) {this.lastTapTime curTimeclearTimeout(this.clickTimer)// 双击return this.handleMovableDbClick(e, index)}}this.lastTapTime curTime;clearTimeout(this.clickTimer);this.clickTimer setTimeout(() {// 单击this.handleMovableOnClick(e, index)}, this.clickDelay)},// 图片单击事件(关闭预览)handleMovableOnClick(e, index) {this.modal falsesetTimeout(() {this.$emit(close, false)}, 100)},// 图片双击事件handleMovableDbClick(e, index) {let item this.picList[index]item.scale item.scale 2 ? 2 : 1this.$set(this.picList, index, item)this.$forceUpdate()},handleChangeSlide(event) {this.current event.detail?.current || 0this.$emit(change-slide, this.current)this.resetScale(this.current)},resetScale(index) {this.picList.forEach((element, idx) {if (idx ! index) {element.scale 1}})this.$forceUpdate()}}
}style langless scoped
.img-preview {position: fixed;top: 0;left: 0;right: 0;bottom: 0;z-index: 9999;opacity: 0;
}
.img-preview-bg {position: absolute;top: 0;left: 0;right: 0;bottom: 0;background: rgba(0, 0, 0, 1);z-index: 1;
}
.movable-area {height: 100%;width: 100%;overflow: hidden;
}
.movable-view {height: 100%;width: 100%;
}.img-preview-bg {position: absolute;top: 0;left: 0;right: 0;bottom: 0;background: rgba(0, 0, 0, 1);z-index: 1;
}
.preivew-swiper{width: 100%;height: 100%;display: flex;flex-direction: column;align-items: center;box-sizing: border-box;// padding-top: calc((100vh - 100vw) * 0.356);position: relative;z-index: 2;
}
.preivew-swiper-fullscreen {padding-top: calc((100vh - 100vw) * 0.5);
}
.swiper-container {width: 100%;height: 100%;box-sizing: border-box;display: flex;flex-direction: column;align-items: center;position: relative;z-index: 2;
}
.swiper-wrapper,
.swiper-slide {width: 100% !important;height: 100%;display: flex;align-items: center;
}
.swiper-slide-single {height: 133.34vw;
}
.preview-img {width: 100%;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);max-height: 100%;max-width: 100%;
}
/stylecss不太全截取了一部分
主要是movable-view组件的一些属性配置和事件触发这里有一点需要注意就是在图片放大的情况下移动图片或触发swiper的滑动这里就出现了一个问题我搞了半天但是还是没有解决
怎么阻止swiper手动切换
阻止冒泡事件event.stopPropagation()
uniapp中禁止 event.preventDefault()event.stopPropagation() 要想阻止冒泡事件只能用事件修饰符显然事件修饰符不能根据条件修改这个路不通
swiper有没有什么可以禁止滑动的属性呢有的
disable-touch
查了一下swiper果然有个属性disable-touch很开心终于可以根据条件阻止swiper滑动了当在movable-view中touchmove且scale!1的时候disable-touch设为true反之为false 但是当在小程序中测试时发现这个属性并不管用后来发现该属性在小程序中只有初始化时有用不能做到动态变更
swiper-item添加touchmove
网上很火的解决方案都在21年左右的但是尝试了一下行不通不好用
写一个伪类用一个蒙层盖住swiper
.swiper {position: relative;:after {content: ;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 2;}
}这个方法很好用之前在别的需求中用过盖住之后拖动肯定就不滑动了但是现在的需求显然不能这么用因为movable-view在swiper中需要拖动
最后效果
小程序的swiper阻止切换没有实现同时该组件在小程序端明显卡段动画不流畅也没有native那种回弹的效果跟产品商量了一下也对比了一下决定来个AB实验
小程序端直接用uni.previewImageAPI毕竟用户就是想放大看看图片没必要做那么多嵌套动画流畅体验敢强最重要至于关闭定位索引和在弹框slot别的内容这些暂时在小程序端先不做H5端用自己写的组件如上因为uni.previewImage在H5端的效果一般并且不能双击放大其余的动画流畅度和性能都一样暂时先这样了也没有过多的人力去研究这个H5的动画也没必要做个引擎之类的
参考
移动端单指移动和双指缩放的实现uniapp移动端图片双指缩放、单指拖动、双击缩放dcloudio/uni-appuniapp使用 movable-area movable-view 实现图片双指缩放、鼠标单击缩小双击放大、图片及标记点功能微信小程序swiper禁止用户滑动苛学加/previewImage
如果有需要增加图片旋转或者长按事件等可以参考这个可以结合一下看看就到这里吧预览图有同学需要可以找我要我看见就会回复拜拜~~~