我理解Fabric.js在同一画布中内置了对drag-n-drop的支持。
我们如何让它适用于多个画布?
或者来自非画布html元素,例如桌子上的图像?
答案 0 :(得分:2)
使用
canvas.observe("object:moving", function (event) {});
如果event.e.clientY和event.e.clientX在画布之外,则:
var activeObject = canvas.getActiveObject();
存储在全局dragImage var
中activeObject.clone(function (c) { dragImage = c; });
canvas.remove(activeObject);
然后在窗口鼠标移动事件中,您可以使用src = dragImage.src放置一个img并按照光标。
function mousemove(e){
if (dragImage != null) {
$("#dragimage").show();
$("#dragimage").css("left", e.clientX);
$("#dragimage").css("top", e.clientY);
return;
}else{
$("#dragimage").hide();
}
}
在窗口事件mouseup上,如果dragImage!= null并且新坐标位于fabric.js画布内,则只需newcanvas.add(dragImage)。
mouseup事件:
if (dragImage != null) {
$([canvas, canvas2]).each(function (i, v) {
if (Intersect([event.clientX, event.clientY],$(v.wrapperEl))) {
dragImage.left = event.clientX - $(v.wrapperEl).offset().left;
dragImage.top = event.clientY - $(v.wrapperEl).offset().top;
v.add(dragImage);
}
});
dragImage = null;
}
助手相交功能:
function Intersect(point, element) {
return ( point[0] > element.offset().left
&& point[0] < element.offset().left + element.width()
&& point[1] < element.offset().top + element.height()
&& point[1] > element.offset().top
);
}
#dragimage的css:
#dragimage
{
opacity:0.5;
max-width:100px;
max-height:200px;
position:fixed;
top:0px;
left:0px;
z-index:90000;
}
我不能做一个小提琴,但我在不到30分钟的时间里就在我们巨大的相册编辑器上实现了这一点。也适用于文本,但对于文本,您必须使用dragImage = getActiveObject()。clone() 任何问题随时都可以问。
答案 1 :(得分:0)
在Fabric.js中可以在画布之间进行拖放,但是需要对私有属性进行一些操作。因此,不能保证它不能与Fabric.js的未来版本一起使用。
有效演示: https://jsfiddle.net/mmalex/kdbu9f3y/
视频捕获: https://youtu.be/nXZgCmIrpqQ
主要功能:
✓可以在任意数量的画布(不仅是两个)之间拖放,
✓可以在画布之间来回拖动而不会中断,
✓可以变换(镜像)掉落的图像而不会中断操作。
第1步 –准备画布,加载图像,安排演示所需的一切:
//create two canvases
var canvas0El = document.getElementById("c0");
canvas0El.width = canvas0El.offsetWidth;
canvas0El.height = canvas0El.parentElement.offsetHeight;
var canvas1El = document.getElementById("c1");
canvas1El.width = canvas1El.offsetWidth;
canvas1El.height = canvas1El.parentElement.offsetHeight;
var canvas0 = new fabric.Canvas('c0');
canvas0.setBackgroundColor('rgba(19, 19, 19, 0.25)');
canvas0.renderAll();
var canvas1 = new fabric.Canvas('c1');
canvas1.setBackgroundColor('rgba(92, 18, 18, 0.25)');
canvas1.renderAll();
// add loaded image on left canvas
var onImageLoaded = function(oImg) {
oImg.originX = "center";
oImg.originY = "center";
oImg.left = this.x;
oImg.top = this.y;
canvas0.add(oImg);
oImg.canvas = canvas0;
imgArrow = oImg;
};
var config = { crossOrigin: 'anonymous' };
var baseUrl = "http://mbnsay.com/rayys/images";
var url0 = baseUrl + "/arrow-right-green.png";
var url1 = baseUrl + "/arrow-right-icon.png";
var url2 = baseUrl + "/arrow-right-blue.png";
// load some images
fabric.Image.fromURL(url0, onImageLoaded.bind({ x: 56, y: 96 }), config);
fabric.Image.fromURL(url0, onImageLoaded.bind({ x: 156, y: 96 }), config);
fabric.Image.fromURL(url1, onImageLoaded.bind({ x: 56, y: 2*96 }), config);
fabric.Image.fromURL(url1, onImageLoaded.bind({ x: 156, y: 2*96 }), config);
fabric.Image.fromURL(url2, onImageLoaded.bind({ x: 56, y: 3*96 }), config);
fabric.Image.fromURL(url2, onImageLoaded.bind({ x: 156, y: 3*96 }), config);
步骤2 –在两个画布上订阅object:moving
事件,并观察对象中心何时跨越画布边界。当物体越过边界时,必须是
var onObjectMoving = function(p) {
var viewport = p.target.canvas.calcViewportBoundaries();
if (p.target.canvas === canvas0) {
if (p.target.left > viewport.br.x) {
console.log("Migrate: left -> center");
migrateItem(canvas0, canvas1, p.target);
return;
}
}
if (p.target.canvas === canvas1) {
if (p.target.left < viewport.tl.x) {
console.log("Migrate: center -> left");
migrateItem(canvas1, canvas0, p.target);
return;
}
}
};
canvas0.on("object:moving", onObjectMoving);
canvas1.on("object:moving", onObjectMoving);
第3步 –解决方案的核心是在画布之间迁移对象而不中断鼠标操作。很难解释,只需遵循代码中的注释即可。
var migrateItem = function(fromCanvas, toCanvas, pendingImage) {
// Just drop image from old canvas
fromCanvas.remove(pendingImage);
// We're going to trick fabric.js,
// so we keep internal transforms of the source canvas,
// in order to inject it into destination canvas.
var pendingTransform = fromCanvas._currentTransform;
fromCanvas._currentTransform = null;
// Make shortcuts for fabric.util.removeListener and fabric.util.addListener
var removeListener = fabric.util.removeListener;
var addListener = fabric.util.addListener;
// Re-arrange subscriptions for source canvas
{
removeListener(fabric.document, 'mouseup', fromCanvas._onMouseUp);
removeListener(fabric.document, 'touchend', fromCanvas._onMouseUp);
removeListener(fabric.document, 'mousemove', fromCanvas._onMouseMove);
removeListener(fabric.document, 'touchmove', fromCanvas._onMouseMove);
addListener(fromCanvas.upperCanvasEl, 'mousemove', fromCanvas._onMouseMove);
addListener(fromCanvas.upperCanvasEl, 'touchmove', fromCanvas._onMouseMove, {
passive: false
});
if (isTouchDevice) {
// Wait 500ms before rebinding mousedown to prevent double triggers
// from touch devices
var _this = fromCanvas;
setTimeout(function() {
addListener(_this.upperCanvasEl, 'mousedown', _this._onMouseDown);
}, 500);
}
}
// Re-arrange subscriptions for destination canvas
{
addListener(fabric.document, 'touchend', toCanvas._onMouseUp, {
passive: false
});
addListener(fabric.document, 'touchmove', toCanvas._onMouseMove, {
passive: false
});
removeListener(toCanvas.upperCanvasEl, 'mousemove', toCanvas._onMouseMove);
removeListener(toCanvas.upperCanvasEl, 'touchmove', toCanvas._onMouseMove);
if (isTouchDevice) {
// Unbind mousedown to prevent double triggers from touch devices
removeListener(toCanvas.upperCanvasEl, 'mousedown', toCanvas._onMouseDown);
} else {
addListener(fabric.document, 'mouseup', toCanvas._onMouseUp);
addListener(fabric.document, 'mousemove', toCanvas._onMouseMove);
}
}
// We need this timer, because we want Fabric.js to complete pending render
// before we inject, because it causes some unpleasant image jumping.
setTimeout(function() {
// Add image to destination canvas,
pendingImage.scaleX *= -1;
pendingImage.canvas = toCanvas;
pendingImage.migrated = true;
toCanvas.add(pendingImage);
// and inject transforms from source canvas
toCanvas._currentTransform = pendingTransform;
// as we have mirrored the image, we mirror transforms too
toCanvas._currentTransform.scaleX *= -1;
toCanvas._currentTransform.original.scaleX *= -1;
// finally don't forget to make pasted object selected
toCanvas.setActiveObject(pendingImage);
}, 10);
};
玩得开心!