欢迎关注 『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: '', //文件url
language: '', //使用教程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().screenWidth
this.imgNum = 4
this.picListIndex = '1/' + this.imgNum
this.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 = 0
this.quickStartX = 0
this.quickScale = 1
this.scaleValue = 1
},
scale(event) {
// 缩放过程事件
this.scaleValue = event.detail.scale
},
handleMovableViewChange(event) {
// movable-view @change事件
this.moveX = event.detail.x
},
// 触控开始
handleTouchStart(event) {
this.quickStartX = this.moveX
this.quickScale = this.scaleValue
this.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].clientX
this.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) return
if (touchDistance > 0) {
console.log('向右滑动')
changeText = '向右滑动'
// 到底了
if (this.imageListIndex == 0) return
this.imageListIndex--
// 快照和数据重置
this.reset()
} else if (touchDistance < 0) {
console.log('向左滑动')
changeText = '向左滑动'
// 到底了
if (this.imageListIndex == this.localImageList.length - 1) return
this.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.isOffset
const width = `${100 * this.localImageList.length}vw`
let base = -1 * this.screenWidth * this.imageListIndex
const 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』 专栏,持续更新中
『未完待续』