有时候我们会碰到这样的需求:在原生组件上,例如:canvas,map等组件,在这些组件上想要拖动其他非原生组件,例如:view,button等,但是原生组件层级永远是最高的,即你在view或者button上绑定的事件是监听不到的。
在官方文档中:为了解决原生组件层级最高的限制。小程序专门提供了 cover-view
和 cover-image
组件,可以覆盖在部分原生组件上面。这两个组件也是原生组件,但是使用限制与其他原生组件有所不同。
所以我们使用cover-view代替view。监听cover-view组件的bindtouchmove(拖动)事件实时更新cover-view组件的left和top值来改变cover-view组件的位置,以达到拖动的目的,但是在拖动cover-view组件时会出现抖动问题,其中在ios下有轻微抖动,在安卓下抖动较为剧烈,用户体验比较差。如何解决这个问题呢?
最终方案:
放弃使用cover-view组件,重新使用view组件。但是不是通过监听view组件本身的bindtouchmove(拖动)事件来改变view的位置,而是通过监听view组件的父组件的bindtouchmove(拖动)事件来判断当前点击的位置是否在view组件的范围内,如果当前触屏点在某一个view组件的大小范围内,则改变该view组件的left与top值来达到改变view的位置。
wxml:
<view class="canvasBox" bindtouchmove='moving' bindtouchstart='moveStart' bindtouchend='moveEnd'>
<view class="player"
style="left:{{left}}px;top:{{top}}px;">
</view>
</view>
wxss:
.canvasBox{
position: relative;
top:0;
left:0;
width: 750rpx;
height:800rpx;
background:#eee;
}
.canvasBox .player{
position: absolute;
width: 60rpx;
height:60rpx;
background: green;
color:#fff;
text-align: center;
line-height: 60rpx;
border-radius: 50%;
box-shadow: 0 12rpx 16rpx #000;
border: 6rpx solid red;
box-sizing: border-box;
top:50rpx;
left:50rpx;
}
js:
const app = getApp()
var isClick = false;
var lastX,lastY;
var startX,startY;
Page({
data: {
left:100,
top:100
},
//移动球员
movePlayer: function (x,y,obj) {
if (x <= 0) {
x = 0;
}
if (x >= 325) {
x = 325;
}
if (y <= 0) {
y = 0;
}
if (y >= 350) {
y = 350;
}
obj.setData({
left: x,
top: y
});
},
moveStart:function(e){
console.log(e);
var x = Math.floor(e.touches[0].clientX);
var y = Math.floor(e.touches[0].clientY);
lastX = this.data.left;
lastY = this.data.top;
startX = x;
startY = y;
//判断第一触点是否在view组件的范围内
if (startX >= lastX && startX <= lastX + 30 && startY >= lastY && startY <= lastY + 30){
isClick = true;
}else{
isClick = false;
}
},
moveEnd:function(){
isClick = false;
lastX = this.data.left;
lastY = this.data.top;
},
moving:function(e){
console.log(e);
var x = Math.floor(e.changedTouches[0].clientX);
var y = Math.floor(e.changedTouches[0].clientY);
if(isClick){
this.movePlayer(x - 25, y - 25,this);
}
},
onLoad: function () {
}
})
小伙伴们如果有任何疑问,请在下方留言。