Joint.js在两个paper之间实现元素的拖放

9
我正在对两个纸张之间实现拖放功能。但是,在处理拖动元素的偏移量与光标位置同步时,我被困住了,因为我的HTML body中有两个纸张。我对CSS的经验非常少,这可能会导致元素定位的问题。
应用场景:
用户从纸张2点击元素并开始拖动,然后移动到纸张1。当指针抬起时,该元素的克隆将添加到纸张1上,位置在纸张1中的光标位置。
我的解决策略是:
当用户点击mousedown时:
1.动态创建一个div
2.在新的div中创建第三个纸张,称其为"flypaper"。复制要克隆的元素,并将其添加到"flypaper"中。
3.创建一个mousemove监听器,以使包含"flypaper"的div随鼠标移动。
4.添加一个mouseup事件,当用户释放按钮时,将该元素克隆添加到"paper2"中。
5.清理"flypaper" div和事件。
<body>
<div id="paper" class="paper" style="border-style: solid;border-width: 5px;width:600px"></div>
<div id="paper2" class="paper" style="border-style: solid;border-width: 5px;width:600px;display:inline-block" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<script>
    var graph = new joint.dia.Graph;
    var paper = new joint.dia.Paper({
        el: $('#paper'),
        width: 600,
        height: 200,
        model: graph,
        gridSize: 1

    });
    var rect = new joint.shapes.basic.Rect({
        position: { x: 100, y: 30 },
        size: { width: 100, height: 30 },
        attrs: { rect: { fill: 'blue' }, text: { text: 'my box', fill: 'white' } }
    });
    graph.addCells([rect]);
    ////////////////////////////////////////////////////////
    var graph2 = new joint.dia.Graph;
    var paper2 = new joint.dia.Paper({
        el: $('#paper2'),
        width: 600,
        height: 200,
        model: graph2,
        gridSize: 1
    });
    paper2.on('cell:pointerup',function (cellView, evt, x, y) {
        var rect4 = new joint.shapes.basic.Rect({
            position: { x: 10, y: 50 },
            size: { width: 100, height: 30 },
            attrs: { rect: { fill: 'blue' }, text: { text: 'my box', fill: 'white' } }
        });

        graph.addCells([rect4]);
    });
    paper2.on('cell:pointerdown',function (cellView, evt, x, y) {
        $('body').append('<div id="flyPaper" class="box" style="position: fixed;z-index: 100;display:block;opacity:.7;"></div>');
        var graph3 = new joint.dia.Graph;
        var paper3 = new joint.dia.Paper({
            el: $('#flyPaper'),
            width: 600,
            height: 200,
            model: graph3,
            gridSize: 1
        });
        var rect3 = new joint.shapes.basic.Rect({
            position: { x: 10, y: 50 },
            size: { width: 100, height: 30 },
            attrs: { rect: { fill: 'blue' }, text: { text: 'my box', fill: 'white' } }
        });

        graph3.addCells([rect3]);
        $('body').mousemove(function(e){
            var mouseX   =  e.pageX; //get mouse move position
            var mouseY   =  e.pageY;
            $( "div.box" ).offset({ top: mouseY, left: mouseX });
            // $('div.box',this).css({'top': boxPositionY,'left': boxPositionX})
        });

    });

    var rect2 = new joint.shapes.basic.Rect({
        position: { x: 10, y: 50 },
        size: { width: 100, height: 30 },
        attrs: { rect: { fill: 'blue' }, text: { text: 'my box', fill: 'white' } }
    });
    graph2.addCells([rect2]);
</script>
</body>
1个回答

25

我有同样的问题(并且有客户不想为在 rappid中新增的此功能付费,而该功能可用于jointjs)。因此,以下是可能会对其他人有所帮助的代码片段:

步骤与您指出的相同:
1.动态创建一个div
2.在新的div中创建第三个paper,称其为“flypaper”复制要克隆的元素并将其添加到“flypaper”
3.创建一个mousemove监听器,以通过鼠标移动div包含的“flypaper”
4.添加mouseup事件,当用户释放按钮时,在“paper2”中添加元素的克隆
5.清理“flypaper” div和事件。

解决您的问题的方法是使用cellView.model.clone()来添加正确的元素,然后使用$.offset, $.width() & $.height()进行一些计算,以获取正确的飞行纸张位置,并检查删除事件是否发生在目标纸张上。

在codepen上查看

<body>
<div id="paper" class="paper" style="border-style: solid;border-width: 5px;width:600px"></div>
<div id="paper2" class="paper" style="border-style: solid;border-width: 5px;width:600px;display:inline-block"></div>
<script>
    // Canvas where sape are dropped
    var graph = new joint.dia.Graph,
      paper = new joint.dia.Paper({
        el: $('#paper'),
        model: graph
      });

    // Canvas from which you take shapes
    var stencilGraph = new joint.dia.Graph,
      stencilPaper = new joint.dia.Paper({
        el: $('#stencil'),
        height: 60,
        model: stencilGraph,
        interactive: false
      });

    var r1 = new joint.shapes.basic.Rect({
      position: {
        x: 10,
        y: 10
      },
      size: {
        width: 100,
        height: 40
      },
      attrs: {
        text: {
          text: 'Rect1'
        }
      }
    });
    var r2 = new joint.shapes.basic.Rect({
      position: {
        x: 120,
        y: 10
      },
      size: {
        width: 100,
        height: 40
      },
      attrs: {
        text: {
          text: 'Rect2'
        }
      }
    });
    stencilGraph.addCells([r1, r2]);

    stencilPaper.on('cell:pointerdown', function(cellView, e, x, y) {
      $('body').append('<div id="flyPaper" style="position:fixed;z-index:100;opacity:.7;pointer-event:none;"></div>');
      var flyGraph = new joint.dia.Graph,
        flyPaper = new joint.dia.Paper({
          el: $('#flyPaper'),
          model: flyGraph,
          interactive: false
        }),
        flyShape = cellView.model.clone(),
        pos = cellView.model.position(),
        offset = {
          x: x - pos.x,
          y: y - pos.y
        };

      flyShape.position(0, 0);
      flyGraph.addCell(flyShape);
      $("#flyPaper").offset({
        left: e.pageX - offset.x,
        top: e.pageY - offset.y
      });
      $('body').on('mousemove.fly', function(e) {
        $("#flyPaper").offset({
          left: e.pageX - offset.x,
          top: e.pageY - offset.y
        });
      });
      $('body').on('mouseup.fly', function(e) {
        var x = e.pageX,
          y = e.pageY,
          target = paper.$el.offset();

        // Dropped over paper ?
        if (x > target.left && x < target.left + paper.$el.width() && y > target.top && y < target.top + paper.$el.height()) {
          var s = flyShape.clone();
          s.position(x - target.left - offset.x, y - target.top - offset.y);
          graph.addCell(s);
        }
        $('body').off('mousemove.fly').off('mouseup.fly');
        flyShape.remove();
        $('#flyPaper').remove();
      });
    });
</script>
</body>

嗨@François-XavierAeberhard。我正在尝试你的代码,但是如果我需要在拖动后更改进程的名称怎么办?如果我拖动到两个矩形上,我想给这两个矩形分别命名。 - Keerthi Reddy Yeruva
@Keerthi Reddy Yeruva,我有同样的需求。你找到解决方案了吗?谢谢! - Joshua
@konekoya,您能详细说明一下吗?我不确定我理解了这个问题。 - François-Xavier Aeberhard
这是双击事件。类似地,还有一个拖放事件 paper.on('cell:pointerdblclick', (cellView, e, x, y) => { graph.getCell(cellView.model.id).attributes.attrs['.label'].text = "更改名称"; }); - Neethu George
我注意到 flyPaper 变量没有被使用。有什么奇怪的地方使它仍然是必要的吗? - Egor Hans
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接