javascriptjquerycanvasmxgraphjgraph

How to drag html shapes into mxgraph canvas


I want to drag and drop those 3 shapes into mxgraph canvas (which is the black area).

Note: I want to fully preserve the drag element on the canvas, including shape, size, color, text, etc.

I don't know whether insertVertex does it work. Dragging the orange,red or other box in to the dark area currently does not work.

var graph;

function initCanvas() {
//This function is called onload of body itself and it will make the mxgraph canvas
  graph = new mxGraph(document.getElementById('graph-wrapper'));
}


function handleDrag(event) {
  event.dataTransfer.setData("draggedId", event.target.id);
}

function allowDrop(event) {
  event.preventDefault();
}

function handleDrop(event) {
  console.log('dropped');
  event.preventDefault();
  var parent = graph.getDefaultParent();
  graph.getModel().beginUpdate();

  var element = document.getElementById(event.dataTransfer.getData('draggedId'))
  var gridRect = document.getElementById('graph-wrapper').getBoundingClientRect();
  var targetX = event.x - gridRect.x;
  var targetY = event.y - gridRect.y;

  try {
    graph.insertVertex(parent, null, element, targetX, targetY);
  } finally {
    // Updates the display
    graph.getModel().endUpdate();
  }
}
#graph-wrapper {
  background: #333;
  width: 100%;
  height: 528px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--
  Copyright (c) 2006-2013, JGraph Ltd
  
  Dynamic toolbar example for mxGraph. This example demonstrates changing the
  state of the toolbar at runtime.
-->
<html>

<head>
  <title>Toolbar example for mxGraph</title>
  <script type="text/javascript">
    mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
  </script>
  <script type="text/javascript" src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
</head>

<body onload="initCanvas()">
  <h4>Drag Boxes onto the black canvas and see what happens</h4>
 
  
  <div>
    <div draggable="true" id="shape_1"  ondragstart="handleDrag(event)" style="width: 100px; height: 100px; border-radius: 50%; background: red; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">Pipe</div>
    <div draggable="true" id="shape_2"  ondragstart="handleDrag(event)" style="width: 100px; height: 100px; border-radius: 5%; background: orange; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">Team</div>
    <div draggable="true" id="shape_3"  ondragstart="handleDrag(event)" style="width: 100px; height: 64px; background: #009688; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center; border-radius: 207px; flex-direction: column;">
        <div>  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg></div>
        <div>Info</div>
    </div>
    
  </div>
  
 

  <div id="graph-wrapper" ondrop='handleDrop(event)' ondragover="allowDrop(event)">
  </div>
</body>

</html>


Solution

  • In mxgraph, normally you do that using so-called "stencil". You can define your own custom shapes using XML, and then use mxgraph to take care of the rest. RTFM :)

    If you don't want to follow this baseline path, then things will become increasingly harder. Anyway, back to the point - you can use this example (it's an adopted version of the "sidebar" code you can find in the mxgraph) - for the details on functions see the Sidebar.js:

    var graph;
    
    function initCanvas() {
    
      //This function is called onload of body itself and it will make the mxgraph canvas
      graph = new mxGraph(document.getElementById('graph-wrapper'));
      graph.htmlLabels = true;
      graph.cellsEditable = false;
    
      // render as HTML node always. You probably won't want that in real world though
      graph.convertValueToString = function(cell) {
        return cell.value;
      }
    
      const createDropHandler = function (cells, allowSplit) {
        return function (graph, evt, target, x, y) {
          const select = graph.importCells(cells, x, y, target);
          graph.setSelectionCells(select);
        };
      };
    
      const createDragPreview = function (width, height) {
        var elt = document.createElement('div');
        elt.style.border = '1px dashed black';
        elt.style.width = width + 'px';
        elt.style.height = height + 'px';
        return elt;
      };
    
      const createDragSource = function (elt, dropHandler, preview) {
        return mxUtils.makeDraggable(elt, graph, dropHandler, preview, 0, 0, graph.autoscroll, true, true);
      };
    
      const createItem = (id) => {
    
        const elt = document.getElementById(id);
        const width = elt.clientWidth;
        const height = elt.clientHeight;
    
        const cell = new mxCell('', new mxGeometry(0, 0, width, height), 'fillColor=none;strokeColor=none');
        cell.vertex = true;
        graph.model.setValue(cell, elt);
    
        const cells = [cell];
    
        const bounds = new mxRectangle(0, 0, width, height);
        createDragSource(elt, createDropHandler(cells, true, false, bounds), createDragPreview(width, height), cells, bounds);
      };
    
    
      createItem("shape_1");
      createItem("shape_2");
      createItem("shape_3");
    }
    <html>
    
    <head>
        <title>Toolbar example for mxGraph</title>
        <style>
            #graph-wrapper {
                background: #333;
                width: 100%;
                height: 528px;
            }
        </style>
        <script type="text/javascript">
            mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
        </script>
        <script src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
        <script src="./app.js"></script>
    </head>
    
    <body onload="initCanvas()">
        <h4>Drag Boxes onto the black canvas and see what happens</h4>
    
        <div>
            <div id="shape_1"
                style="width: 100px; height: 100px; border-radius: 50%; background: red; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
                Pipe
            </div>
    
            <div draggable="true" id="shape_2"
                style="width: 100px; height: 100px; border-radius: 5%; background: orange; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
                Team
            </div>
            
            <div draggable="true" id="shape_3"
                style="width: 100px; height: 64px; background: #009688; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center; border-radius: 207px; flex-direction: column;">
                <div> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
                        <path d="M0 0h24v24H0V0z" fill="none" />
                        <path
                            d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" />
                    </svg></div>
                <div>Info</div>
            </div>
        </div>
    
        <div id="graph-wrapper">
        </div>
    </body>
    
    </html>

    Note that your code, and the other answer focuses on generic drag-n-drop, which is not applicable to mxgraph. You need to use library-specific code.