[英]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.