簡體   English   中英

在fabric.js中模擬路徑對象的自由繪制

[英]Simulating free drawing of path objects in fabric.js

我正在嘗試模擬 fabric.js canvas 中路徑 object 的自由繪圖。

我在 javascript object 中有一個步驟的“記錄”,例如:

var dataset = [{
  "type": "move",
  "value": [
    [30, 257, "2022-03-22T10:16:56.882Z"],
    [58, 271, "2022-03-22T10:16:56.898Z"],
    [79, 281, "2022-03-22T10:16:56.914Z"],
    [91, 282, "2022-03-22T10:16:56.931Z"],
    [95, 282, "2022-03-22T10:16:56.948Z"],
    [96, 281, "2022-03-22T10:16:56.963Z"],
    [97, 281, "2022-03-22T10:16:56.981Z"]
  ]
},
{
  "type": "draw",
  "value": [
    [97, 281, "2022-03-22T10:16:57.046Z"],
    [98, 281, "2022-03-22T10:16:57.070Z"],
    [103, 279, "2022-03-22T10:16:57.083Z"],
    [106, 278, "2022-03-22T10:16:57.098Z"],
    [114, 274, "2022-03-22T10:16:57.114Z"],
    [133, 268, "2022-03-22T10:16:57.130Z"]
  ]
}]

value是一個數組數組,包含 canvas 上的坐標 (x, y) 和時間戳。 它是在 canvas 上記錄用戶交互的結果。

我設法重新創建了一個移動的 cursor ( "type": "move" ),但我在重新創建繪圖過程 ( "type": "draw" ) 時遇到了麻煩,因為它涉及三個鼠標事件('mousedown'、'mousemove' 和 'mouseup ').

現在,我使用兩個嵌套的異步函數在 object 內部導航,並在 canvas 周圍移動 cursor。

var time;

autoDrawing(dataset, function() {
   console.log('finished');
});

async function autoDrawing(dataset, callback) {
   time = new Date(dataset[0].time);
   for (let i = 0; i < dataset.length; ++i) {
       await draw(dataset[i]);
   }
   callback();
}

function draw(data) {
    return new Promise(resolve => {
        if (data.type === 'move') {
            console.log('moving');
            moveCursor(data.value, false, function() { resolve('') });
        } else if (data.type === 'draw') {
            console.log('drawing');
            moveCursor(data.value, true, function() { resolve('') });
        } else {
            resolve('');
        }
   });
}

async function moveCursor(moves, draw, callback) {
     // The canvas object is stored inside the DOM element, in the fabric property.
     // This is because I have different canvas for different layers.
     let activecanvas = document.getElementsByClassName('canvas-container active')[0].firstChild.fabric;
     if (draw) {
          activecanvas.fire('mouse:down', {
              x: moves[0][0],
              y: moves[0][1]
          });
          activecanvas.renderAll();
     }
     for (j = 0; j < moves.length; j++) {
          await movement(moves[j], draw);
     }
     if (draw) {
          activecanvas.fire('mouse:up', {
              x: moves[moves.length - 1][0],
              y: moves[moves.length - 1][1]
          });
          activecanvas.renderAll();
     }
     callback();

     function movement(m, draw) {
         return new Promise(function(resolve, reject) {
              let newtime = new Date(m[2]);
              if (draw) {
                   activecanvas.fire('mouse:move', {
                        x: m[0],
                        y: m[1]
                   });
                   activecanvas.renderAll();
              }
              // mousecursor is a circle that substitutes the mouse cursor on an other canvas.
              mousecursor.set({
                   top: m[1],
                   left: m[0]
              }).setCoords().canvas.renderAll();
              // waitMap is just a setTimeout with the duration/callback position inverted
              waitMap((newtime - time) / 1000, function() {
                   time = newtime;
                   resolve('')
              })
         })
     }
}

我正在使用 fabric.js canvas 的fire方法,但我沒有找到任何示例,所以也許我沒有以正確的方式使用它。

我設法通過使用 javascript 鼠標事件使其工作。 我在上層 fabric.js canvas 上觸發了一個 mousedown 事件,然后我觸發了多個 mousemove 事件,最后觸發了一個 mouseup 事件。 總結:

let activecanvas = document.getElementsByClassName('canvas-container active')[0].getElementsByClassName('upper-canvas')[0];
if (draw) { simulateMouseEvent(activecanvas, 'mousedown', moves[0][0], moves[0][1]); }
for (j = 0; j < moves.length; j++) {
     await movement(moves[j], draw);
}
if (draw) { simulateMouseEvent(activecanvas, 'mouseup', moves[moves.length - 1][0], moves[moves.length - 1][1]); }

function movement(m, draw) {
      return new Promise(function(resolve, reject) {
             let newtime = new Date(m[2]);
             if (draw) { simulateMouseEvent(activecanvas, 'mousemove', m[0], m[1]); }
             mousecursor.set({
                  top: m[1],
                  left: m[0]
             }).setCoords().canvas.renderAll();
             waitMap((newtime - time) / 1000, function() {
                  time = newtime;
                  resolve('')
             })
      })
}

function simulateMouseEvent(e, eventName, x, y) {
    e.dispatchEvent(new MouseEvent(eventName, {
        view: window,
        bubbles: true,
        cancelable: true,
        clientX: x,
        clientY: y,
        button: 0
    }));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM