图形编辑器:防误操作之拖拽阻塞

开发 前端
为了解决这类用户微小操作的问题,我们可以巧妙地给拖拽行为加一个阻塞阈值。具体就是就是按下鼠标后,移动鼠标的距离要大于某个值,我们才认为发生了拖拽,并执行对应工具的逻辑。

大家好,我是前端西瓜哥。

在图形编辑器中,想象这么一个场景,我们撤销了一些重要的操作,然后想选中一个图形,看看它的属性。你点了上去,然后你发现你再也无法重做了。

你以为你点了一下,但其实你点击的时候,鼠标还是小小移动了一点,飘了一个像素点。对编辑器来说,它识别到让图形移动一个像素点的操作,就生成了一个新的版本,然后重做栈(redoStack)被清空了,你退回前的操作就没了。

为了解决这类用户微小操作的问题,我们可以巧妙地给拖拽行为加一个阻塞阈值。具体就是就是按下鼠标后,移动鼠标的距离要大于某个值,我们才认为发生了拖拽,并执行对应工具的逻辑。

下面为我们要实现的效果。此处为了更好地演示效果,将阈值设置得很大。通常设置个 4px 就够了。

图片

可以看到,按下鼠标然后移动,如果移动的位移太小,矩形是不会被移动的,直到达到一定位移阈值后,矩形才会乖乖听话跟随鼠标进行移动。

阈值表示位移距离,使用的是视口坐标系,而不是场景坐标系。

代码改造

原来的逻辑:

let isPressing = false;
let currentTool = null; // 当前工具对象

// 鼠标按下
function handleDown(e) {
isPressing = true;
currentTool.start(e);
}

// 鼠标移动
function handleMove(e) {
if (isPressing) {
currentTool.drag(e);
} else {
// 非拖拽的移动事件
// 比如选择工具停留在图形上,图形要高亮,此时没发生拖拽
currentTool.move(e);
}
}

// 鼠标释放
function handleUp(e) {
currentTool.end(e);
isPressing = false;
}

鼠标按下时,isPressing 设置为 true,表示发生了鼠标按下事件。

此时鼠标再移动,我们就能知道这是一个 “拖拽” 的行为,即按下鼠标不放然后移动鼠标的行为。此时调用工具对象的 drag 方法。

最后鼠标释放,将状态 isPressing 重置。

现在我们进行改造。

let isPressing = false;
let currentTool = null; // 当前工具对象

let isEnableDragging = false; // 是否调用工具对象的 drag 方法
let startPos = null; // 保存鼠标按下时的坐标
const blockStep = 4; // 阈值

function handleDown(e) {
isPressing = true;
isEnableDragging = false;
startPos = { x: e.clientX, y: e.clientY };
currentTool.start(e);
}

function handleMove(e) {
// 判断位移是否突破阈值,是的话更新状态为 “可拖拽”
if (
!isEnableDragging &&
(Math.abs(e.clientX - startPos.x) > blockStep ||
Math.abs(e.clientX - startPos.x) > blockStep)
) {
isEnableDragging = true;
}
if (isPressing) {
if (isEnableDragging) {
// “可拖拽” 状态,调用工具的 drag 方法
currentTool.drag(e);
}
} else {
currentTool.move(e);
}
}

function handleUp(e) {
currentTool.end(e);

// 初始化状态
isPressing = false;
isEnableDragging = false;
startPos = null;
}

核心思路是引入 isEnableDragging 状态,表示鼠标移动时,是否达到移动的条件。

我们在鼠标移动事件中,计算鼠标按下和鼠标移动之间的距离是否超过某个值,如果超过阈值,就将 isEnableDragging 状态转换为 true。

然后判断 isEnableDragging 为 true,就调用工具对象的 drag 方法。

需要注意的是,不要只用位移距离来判断是否可以拖拽,要配合状态。否则突破阈值后,又移动回来,你会发现你又卡住了,因为此时阈值因为再次计算,没能达到阈值。

所以加了个 isEnableDragging 状态,在第一次突破阈值设置为 true 后,就再也不用计算位移了,之后一直都是可拖拽状态,直到鼠标释放重置状态。

结尾

拖拽阻塞是开发图形编辑器的一点小细节,并不复杂,但能带来很好的用户体验。

责任编辑:姜华 来源: 前端西瓜哥
相关推荐

2023-10-19 10:12:34

图形编辑器开发缩放图形

2023-08-31 11:32:57

图形编辑器contain

2023-09-07 08:24:35

图形编辑器开发绘制图形工具

2023-01-18 08:30:40

图形编辑器元素

2023-02-01 09:21:59

图形编辑器标尺

2023-02-06 16:59:57

Canvas编辑器

2023-04-07 08:02:30

图形编辑器对齐功能

2020-10-14 14:00:39

VIM编辑器

2023-09-26 07:39:21

2023-04-10 08:45:44

图形编辑器排列移动功能

2023-09-11 09:02:31

图形编辑器模块间的通信

2023-05-09 08:15:32

图形编辑器撤销重做功能

2024-01-08 08:30:05

光标图形编辑器开发游标

2023-02-09 07:02:30

图形编辑器修改图形

2023-10-08 08:11:40

图形编辑器快捷键操作

2023-10-10 16:04:30

图形编辑器格式转换

2023-08-28 08:10:50

Hex图形编辑器

2023-02-02 14:07:00

图形编辑器Canvas

2023-07-31 08:46:07

图形编辑器图形自动对齐

2024-01-03 08:43:17

图形编辑器旋转控制点缩放控制点
点赞
收藏

51CTO技术栈公众号