『uniapp』自己实现手动图片列表滑动 + 图片手势缩放+ 图片点击缩放(详细图文注释)
目录
- 预览效果
- 思路分析
- 完整代码
- 总结
欢迎关注 『uniapp』 专栏,持续更新中
欢迎关注 『uniapp』 专栏,持续更新中
预览效果
思路分析
这个目前有点问题,就是因为监听触摸导致手机上有点卡顿,体验上不如uni-swiper
主要是为了双指缩放和点击缩放综合运用了movable-area和movable-view,抛砖引玉,仅供参考.
后续找机会优化,也期待评论区的朋友们提点建议.
完整代码
<template><view><!-- 通过定位来控制面板显示 --><view class="box" :style="widthStyle"><view class="bbox" :style="bboxStyle"><movable-area class="movable-area" v-for="(item, index) in localImageList" :style="widthStyle" :key="'key' + index"><movable-view @dblclick="dblclick(index)" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd" @scale="scale" @change="handleMovableViewChange" animation="true" damping="200" friction="2" class="movable-view" direction="all" scale="true" scale-min="1" scale-max="4" :scale-value="scaleList[index]"><view style="padding: 12px; border-bottom: 1px solid #ccc"> 我是一个安装教程,假装我是pdf, </view><view style="height: 5px; background-color: beige"> </view><view>第{{ imageListIndex + 1 }}页</view><br /><image class="lookimg" :src="localImageList[index]" mode="widthFix"></image></movable-view></movable-area></view></view></view>
</template><script>export default {data() {return {// 开始和结束来记录左滑还是右滑,以及滑动距离touchStartX: 0,touchEndX: 0,changeText: '', // 操作moveX: 0, // 内部节点的x定位quickStartX: 0, // 快照scaleValue: 1, // 缩放倍数quickScale: 1, // 快照offset: 0, //偏移量isOffset: false, // 是否叠加偏移量//cscs: false,localImageList: [], //图片本地url列表imgNum: 1, //pdf页数picListIndex: '1/1', //当前图片索引pdfUrl: '', //文件urllanguage: '', //使用教程pdf语言isAndroid: true,imageListIndex: 0, //当前处于第几页isDisableTouch: false, //是否禁止滑动scaleList: new Array(16).fill(1),// scale: 1, // 图片放大倍数moveDirction: '', //移动方向changePageFlag: false, //minMoveLength: 50, //最小移动距离阈值xNow: 0, //当前x坐标 用于判断是否到边界startX: 0, //记录触摸开始时的screenWidth: 0,}},onLoad(option) {this.screenWidth = uni.getSystemInfoSync().screenWidththis.imgNum = 4this.picListIndex = '1/' + this.imgNumthis.localImageList = ['../../static/1.png','../../static/2.png','../../static/3.png','../../static/4.png','../../static/1.png','../../static/2.png','../../static/3.png','../../static/4.png','../../static/1.png','../../static/2.png','../../static/3.png','../../static/4.png','../../static/1.png','../../static/2.png','../../static/3.png','../../static/4.png','../../static/1.png','../../static/2.png','../../static/3.png','../../static/4.png','../../static/1.png','../../static/2.png','../../static/3.png','../../static/4.png','../../static/1.png','../../static/2.png','../../static/3.png','../../static/4.png']},computed: {},props: {isBack: {type: Boolean,default: true},titleSize: {type: String,default: '34'},titleColor: {type: String,default: '#D2D2D2'},background: {type: Object,default: () => {return {background: '#272729'}}}},methods: {//双击缩放dblclick(index) {if (this.scaleList[index] < 1.5) {this.$set(this.scaleList, index, 1.5);} else if (this.scaleList[index] < 2) {this.$set(this.scaleList, index, 2);} else if (this.scaleList[index] >= 2) {this.$set(this.scaleList, index, 1);}},reset() {// 切换面板重置数据this.moveX = 0this.quickStartX = 0this.quickScale = 1this.scaleValue = 1},scale(event) {// 缩放过程事件this.scaleValue = event.detail.scale},handleMovableViewChange(event) {// movable-view @change事件this.moveX = event.detail.x},// 触控开始handleTouchStart(event) {this.quickStartX = this.moveXthis.quickScale = this.scaleValuethis.touchStartX = event.touches[0].clientX},// 触控过程handleTouchMove(event) {// 是否叠加偏移量if (this.moveX == this.quickStartX && this.scaleValue == this.quickScale) {this.isOffset = true} else {this.isOffset = false}// 偏移量this.offset = event.touches[0].clientX - this.touchStartX},// 触控结束handleTouchEnd(event) {this.touchEndX = event.changedTouches[0].clientXthis.detectSwipeDirection()// 是否叠加偏移量this.isOffset = false},// 计算操作情况,判断是否要切换面板detectSwipeDirection() {let changeText = ''const touchDistance = this.touchEndX - this.touchStartX// 小于120像素的滑动不触发左右切换if (Math.abs(touchDistance) < 120) return// x快照和x定位不一致,证明非边界情况if (this.moveX != this.quickStartX) return// x快照和x定位不一致,证明是正在放大缩小if (this.scaleValue != this.quickScale) returnif (touchDistance > 0) {console.log('向右滑动')changeText = '向右滑动'// 到底了if (this.imageListIndex == 0) returnthis.imageListIndex--// 快照和数据重置this.reset()} else if (touchDistance < 0) {console.log('向左滑动')changeText = '向左滑动'// 到底了if (this.imageListIndex == this.localImageList.length - 1) returnthis.imageListIndex++// 快照和数据重置this.reset()}console.log('滑动距离:', Math.abs(touchDistance))this.changeText = changeText + '滑动距离:' + Math.abs(touchDistance)}},computed: {widthStyle() {const width = `${this.screenWidth}px`return {width}},bboxStyle() {// console.log(' uni.getSystemInfoSync().screenWidth', uni.getSystemInfoSync().screenWidth)const isOffset = this.isOffsetconst width = `${100 * this.localImageList.length}vw`let base = -1 * this.screenWidth * this.imageListIndexconst left = this.isOffset ? base + this.offset + 'px' : base + 'px'const transition = 'left 0.1s'// 返回一个对象,包含计算得到的样式return {width,left,transition}}}}
</script>
<style scoped>.box {height: 100vh;position: relative;overflow: hidden;}.bbox {display: flex;left: 0;position: relative;height: 100vh;/* background-color: bisque; */}.movable-view {display: flex;flex-direction: column;align-items: center;justify-content: center;height: 100%;width: 100%;position: relative;}.movable-area {height: 100%;/* background-color: blue; */}.lookimg {height: 100%;width: 100%;display: block;position: relative;top: 0px;left: 0px;border: 0rpx solid #d6d6d7;box-shadow: 0 -3rpx 5rpx 1rpx rgba(0, 0, 0, 0.1), 0 2rpx 5rpx 1rpx rgba(0, 0, 0, 0.1);/* margin-top: 15%; */}
</style>
总结
大家喜欢的话,给个👍,点个关注!给大家分享更多计算机专业学生的求学之路!
版权声明:
发现你走远了@mzh原创作品,转载必须标注原文链接
Copyright 2024 mzh
Crated:2024-4-1
欢迎关注 『uniapp』 专栏,持续更新中
欢迎关注 『uniapp』 专栏,持续更新中
『未完待续』