最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

圖形編輯器中JS實現(xiàn)防誤操作之拖拽阻塞

 更新時間:2023年03月06日 16:13:59   作者:前端西瓜哥  
這篇文章主要為大家介紹了圖形編輯器中JS實現(xiàn)防誤操作之拖拽阻塞實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

圖形編輯器中

在圖形編輯器中,想象這么一個場景,我們撤銷了一些重要的操作,然后想選中一個圖形,看看它的屬性。你點了上去,然后你發(fā)現(xiàn)你再也無法重做了。

你以為你點了一下,但其實你點擊的時候,鼠標(biāo)還是小小移動了一點,飄了一個像素點。對編輯器來說,它識別到讓圖形移動一個像素點的操作,就生成了一個新的版本,然后重做棧(redoStack)被清空了,你退回前的操作就沒了。

為了解決這類用戶微小操作的問題,我們可以巧妙地給拖拽行為加一個 阻塞閾值。具體就是就是按下鼠標(biāo)后,移動鼠標(biāo)的距離要大于某個值,我們才認(rèn)為發(fā)生了拖拽,并執(zhí)行對應(yīng)工具的邏輯。

下面為我們要實現(xiàn)的效果。此處為了更好地演示效果,將閾值設(shè)置得很大。通常設(shè)置個 4px 就夠了。

可以看到,按下鼠標(biāo)然后移動,如果移動的位移太小,矩形是不會被移動的,直到達(dá)到一定位移閾值后,矩形才會乖乖聽話跟隨鼠標(biāo)進(jìn)行移動。

閾值表示位移距離,使用的是視口坐標(biāo)系,而不是場景坐標(biāo)系。

代碼改造

原來的邏輯:

let isPressing = false;
let currentTool = null; // 當(dāng)前工具對象
// 鼠標(biāo)按下
function handleDown(e) {
  isPressing = true;
  currentTool.start(e);
}
// 鼠標(biāo)移動
function handleMove(e) {
  if (isPressing) {
    currentTool.drag(e);
  } else {
    // 非拖拽的移動事件
    // 比如選擇工具停留在圖形上,圖形要高亮,此時沒發(fā)生拖拽
    currentTool.move(e);
  }
}
// 鼠標(biāo)釋放
function handleUp(e) {
  currentTool.end(e);
  isPressing = false;
}

鼠標(biāo)按下時,isPressing 設(shè)置為 true,表示發(fā)生了鼠標(biāo)按下事件。

此時鼠標(biāo)再移動,我們就能知道這是一個 “拖拽” 的行為,即按下鼠標(biāo)不放然后移動鼠標(biāo)的行為。此時調(diào)用工具對象的 drag 方法。

最后鼠標(biāo)釋放,將狀態(tài) isPressing 重置。

現(xiàn)在我們進(jìn)行改造。

let isPressing = false;
let currentTool = null; // 當(dāng)前工具對象
let isEnableDragging = false; // 是否調(diào)用工具對象的 drag 方法
let startPos = null; // 保存鼠標(biāo)按下時的坐標(biāo)
const blockStep = 4; // 閾值
function handleDown(e) {
  isPressing = true;
  isEnableDragging = false;
  startPos = { x: e.clientX, y: e.clientY };
  currentTool.start(e);
}
function handleMove(e) {
  // 判斷位移是否突破閾值,是的話更新狀態(tài)為 “可拖拽”
  if (
    !isEnableDragging &&
    (Math.abs(e.clientX - startPos.x) > blockStep ||
      Math.abs(e.clientX - startPos.x) > blockStep)
  ) {
    isEnableDragging = true;
  }
  if (isPressing) {
    if (isEnableDragging) {
      // “可拖拽” 狀態(tài),調(diào)用工具的 drag 方法
      currentTool.drag(e);
    }
  } else {
    currentTool.move(e);
  }
}
function handleUp(e) {
  currentTool.end(e);
  // 初始化狀態(tài)
  isPressing = false;
  isEnableDragging = false;
  startPos = null;
}

核心思路是引入 isEnableDragging 狀態(tài),表示鼠標(biāo)移動時,是否達(dá)到移動的條件。

我們在鼠標(biāo)移動事件中,計算鼠標(biāo)按下和鼠標(biāo)移動之間的距離是否超過某個值,如果超過閾值,就將 isEnableDragging 狀態(tài)轉(zhuǎn)換為 true。

然后判斷 isEnableDragging 為 true,就調(diào)用工具對象的 drag 方法。

需要注意的是,不要只用位移距離來判斷是否可以拖拽,要配合狀態(tài)。否則突破閾值后,又移動回來,你會發(fā)現(xiàn)你又卡住了,因為此時閾值因為再次計算,沒能達(dá)到閾值。

所以加了個 isEnableDragging 狀態(tài),在第一次突破閾值設(shè)置為 true 后,就再也不用計算位移了,之后一直都是可拖拽狀態(tài),直到鼠標(biāo)釋放重置狀態(tài)。

結(jié)尾

拖拽阻塞是開發(fā)圖形編輯器的一點小細(xì)節(jié),并不復(fù)雜,但能帶來很好的用戶體驗。

以上就是圖形編輯器中JS實現(xiàn)防誤操作之拖拽阻塞的詳細(xì)內(nèi)容,更多關(guān)于JS 拖拽阻塞的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

连云港市| 中山市| 江安县| 台东县| 蓬溪县| 济阳县| 湖南省| 甘肃省| 青州市| 枝江市| 宜州市| 通辽市| 东兴市| 长武县| 建水县| 武定县| 广西| 渭源县| 齐齐哈尔市| 延长县| 大洼县| SHOW| 华容县| 宁安市| 广灵县| 盐津县| 泗阳县| 循化| 茶陵县| 泰顺县| 都江堰市| 澄迈县| 安国市| 武山县| 上蔡县| 新乡市| 金昌市| 黔西县| 韩城市| 尉氏县| 益阳市|