繁体   English   中英

如何在Fabric.js中的画布之间拖放

[英]How to drag and drop between canvases in Fabric.js

我理解Fabric.js在同一个画布中内置了对drag-n-drop的支持。

我们怎样才能使它适用于多个画布?

或者从非画布html元素,例如表格中的图像?

使用

 canvas.observe("object:moving", function (event) {});

如果event.e.clientY和event.e.clientX在画布外,则:

var activeObject = canvas.getActiveObject();

存储在全局dragImage变量中

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()任何问题都可以随意提问。

可以在Fabric.js中拖放画布,但需要对私有属性进行一些操作。 因此,不保证Fabric.js的未来版本可以正常运行

工作演示: https //jsfiddle.net/mmalex/kdbu9f3y/

视频捕获: https //youtu.be/nXZgCmIrpqQ

在fabric.js中的画布之间拖放

主要特征:

✓可以在任意数量的画布(不仅仅是两个)之间拖放,

✓可以不间断地在画布之间来回拖动,

✓可以在不中断操作的情况下转换(镜像)丢弃的图像。


第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在两个画布上object:moving事件,并在对象中心穿过画布边框时观察。 当物体穿过边界时,它必须是

  1. 从源画布中删除,
  2. 粘贴到目标画布,
  3. 迁移内部画布转换(将单独解释)
    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);
    };

玩得开心!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM