一、问题
如何实现页面中元素的滑动功能
二、问题分析
1.实现的效果:
手机端按住元素滑动,元素的位置跟随手的位置变化;电脑端鼠标按住元素滑动。
2.背景:
uniapp开发,项目运行在app端和H5端。更具体的就是目前在做一个盖章的功能,印章图片需要在页面中可以滑动,旋转。
3.实现思路:
滑动:元素的位置动态变化,而元素的位置是通过css样式控制,这样的话可以通过动态改变css样式中的位置来实现,顺着这个方向想下去.......。
三、解决过程
1.首先是这样的(结构、样式、数据)
<template>
<view>
<view>
<image src="/static/pdfImage.jpg" mode="widthFix"></image>
<image class="sealImage" :style="{ 'left': sealLeft + 'px', 'top': sealTop
+ 'px'}" src="/static/sealImage.png" mode="widthFix"></image>
</view>
</view>
</template>
<script>
export default {
data() {
return {
sealLeft: 100,
sealTop: 200
}
},
methods: {
}
}
</script>
<style>
.sealImage{
width: 60px;
height: 60px;
position: absolute;
}
</style>
其中sealImage就是要实现滑动的元素,采用absolute定位(这里是相对于整个页面),top绑定变量sealTop,left绑定变量sealLeft。
2.给元素添加事件
app端手指滑动元素会触发什么事件,想到了@touchmove,那我们看看@touchmove事件能获取到什么数据;
<template>
<view>
<view>
<image src="/static/pdfImage.jpg" mode="widthFix"></image>
<image class="sealImage" :style="{ 'left': sealLeft + 'px', 'top': sealTop
+'px'} src="/static/sealImage.png" mode="widthFix"
@touchmove="handleTouchMove"></image>
</view>
</view>
</template>
<script>
export default {
data() {
return {
sealLeft: 100,
sealTop: 200
}
},
methods: {
handleTouchMove(e){
console.log(e);
}
}
}
</script>
输出的结果中,有滑动到的位置坐标,e.touches[0].clientX为X坐标,e.touches[0].clientY为Y坐标。坐标原点是哪里呢?经过测试知道坐标原点在屏幕可用范围内的左上角。
3.在事件中改变变量sealLeft、sealTop的值
handleTouchMove(e){
console.log(e);
this.sealLeft = e.touches[0].clientX;
this.sealTop = e.touches[0].clientY;
}
到这里元素可以动起来了,你手指滑动元素,元素跟着滑动。
4.效果完善
此时你会发现滑动的效果并不完美,这是因为我们刚才没有考虑元素本身的宽高,或者说我们还要考虑position: absolute是怎么定位的,比如position: absolute;left: 20px;top: 20px; 那是元素的最左边距离页面左边20px,元素的最上边距离页面顶部20px(假设是相对页面定位)。
那我们在将坐标赋值给sealLeft、sealTop时,要稍加处理。
handleTouchMove(e){
console.log(e);
this.sealLeft = e.touches[0].clientX - 30; //X坐标减去元素宽度的一半
this.sealTop = e.touches[0].clientY - 30; //Y坐标减去元素高度的一半
}
假定手指按住元素基本在元素的中心位置,到这里滑动的效果可以了。
5.考虑特殊情况
现在还不能说做完了,你还要考虑特殊情况,对于滑动要考虑会不会滑出指定范围(当前就考虑页面范围)。
滑动时,往上或往下会滑出页面,并且会出现滑出看不到元素的情况,所以这种情况是要避免的。
<script>
export default {
data() {
return {
sealLeft: 0,
sealTop: 0,
windowHeight: 0
}
},
onLoad() {
const system = uni.getSystemInfoSync();
this.windowHeight = system.windowHeight;
},
methods: {
handleTouchMove(e){
console.log(e);
this.sealLeft = e.touches[0].clientX - 30; //X坐标减去元素宽度的一半
let clientY = e.touches[0].clientY;
if(clientY > 0 && clientY < this.windowHeight){
this.sealTop = clientY - 30; //Y坐标减去元素高度的一半
}
}
}
}
</script>
现在才算把滑动的功能做完了。
四、总结
有时候需要滑动的元素并不是相对页面定位的,而是相对于页面中其他元素定位的,这时根据具体情况将获取的坐标处理后赋值给sealLeft、sealTop变量。
有时候元素滑动会引发页面滚动,滑动的效果就会大打折扣,这时需要进一步的处理。
H5端的元素滑动,这里没写,你应该可以搞定的。欢迎交流。