添加边缘限制
背景
开发中,拖拽功能实现就是三个方法 touchstart,touchmove,touchend,也很容易,但是在混合开发中,ios 里面,当 H5 页面里面的拖动进行的时候,手指划出屏幕时,不会触发 touchen 事件,同时,touchmove 事件就会一直存在,那么这就出现了 bug,所有的拖拽事件否不能在执行了,因为上一个的 touchemove 没有结束!怎么解决这个问题呢
原因
MovableView
快速滑动时有时候无法监听 touchEnd
事件
解决方法
在 touchMove 里面进行判断,到达某一个临界点的时候将事件打断即可(或者使用 alert()自带的打断功能)
import React, { useEffect, useState } from "react";
import Taro, { Component } from "@tarojs/taro";
import {
View,
MovableArea,
MovableView,
Image,
Text,
} from "@tarojs/components";
import styles from "./index.module.less";
export default function opusFeed3(props) {
const { listId } = props;
// 记录上次位置信息
const [last, setLast] = useState({ lastX: 0, lastY: 0 });
const [state, setState] = useState([
{
top: 0,
left: 0,
content: "内容1",
},
{
top: 100,
left: 0,
content: "内容222",
},
{
top: 200,
left: 0,
content: "内容333",
},
]);
// 记录上次的位置
const onTouchStart = (e) => {
e.preventDefault();
const { pageY, pageX } = e.changedTouches[0];
setLast({ lastX: pageX, lastY: pageY });
};
// 添加限制:由于快速错拽出屏幕touchend后不触发,需要强制打断
const onTouchMove = (e) => {
const { pageX, pageY } = e.changedTouches[0];
const { lastX, lastY } = last;
console.log("pageY - lastY", pageY - lastY);
// 屏幕宽度
const clientWidth = 400;
// 区域高度
const MovableAreaHeight = 300;
if (pageX - lastX > clientWidth || pageX - lastX < 0) {
e.preventDefault();
console.log("超出X限制");
onTouchEnd();
return;
}
if (pageY - lastY > MovableAreaHeight || pageY - lastY < 0) {
e.preventDefault();
console.log("超出Y限制");
onTouchEnd();
return;
}
};
const onTouchCancel = () => {
console.log("onTouchCancel");
clearTimeout(timer);
let timer = setTimeout(() => {
setState([
{
top: 0,
left: 0,
content: "内容1",
},
{
top: 100,
left: 0,
content: "内容222",
},
{
top: 200,
left: 0,
content: "内容333",
},
]);
// 清零
setLast({ lastX: 0, lastY: 0 });
}, 100);
};
const onTouchEnd = () => {
console.log("onTouchEnd");
clearTimeout(timer);
let timer = setTimeout(() => {
setState([
{
top: 0,
left: 0,
content: "内容1",
},
{
top: 100,
left: 0,
content: "内容222",
},
{
top: 200,
left: 0,
content: "内容333",
},
]);
// 清零
setLast({ lastX: 0, lastY: 0 });
}, 100);
};
const handleChange = (e, i) => {
const test = state.slice();
test[i] = {
top: e.detail.y,
left: e.detail.x,
content: test[i].content,
};
setState(test);
};
return (
<View className={styles.pageBody}>
<MovableArea style="height:300px;width:100%">
{state.map((el, i) => {
return (
<MovableView
style="width:100%;height:100px;border:1px solid red;"
key={i}
direction="all"
x={el.left}
y={el.top}
onTouchStart={onTouchStart}
onTouchMove={onTouchMove}
onTouchEnd={onTouchEnd}
onTouchCancel={onTouchCancel}
onChange={(e) => handleChange(e, i)}
animation={false}
>
<View> {el.content}</View>
</MovableView>
);
})}
</MovableArea>
</View>
);
}
.pageBody {
background: #ffffff
url(https://x0.ifengimg.com/ucms/2021_47/027B7788BC18A519F99A1372340EA4DBFB3A7149_size52_w750_h466.png)
no-repeat 0 -88px;
background-size: 100% auto;
font-family: PingFangSC-Regular, PingFang SC;
display: flex;
flex-direction: column;
overflow-y: scroll;
overflow-x: hidden;
}