如何用可拖动的 html div 替换 raphaeljs 框?

How to replace raphaeljs boxes with draggable html div's?

我正在使用 Raphaeljs 创建 UML Class 图,我以某种方式使用框创建了它,但看起来很糟糕。我想添加可拖动的 div 而不是可拖动的框。这应该与盒子的方式相同,即连接线随着盒子的移动而移动。 如何用可拖动的 div 替换这些框?
任何其他方式做这样的事情也将不胜感激
这是我在这里的第一个或第二个问题。所以,请原谅我,如果问题含糊不清,请查看 fiddle 以了解我实际上在问什么
这就是我用盒子做的

var boxes = [
  {x:200,y:100,text:'User  \n--------------------------------\n Login ()\n 
  Signup () \n ViewProduct ()  '}, 
  {x:400,y:400,text:'Product  \n--------------------------------\n 
  AddProduct ()\n DeleteProduct () \n UpdateProduct ()  '},
  {x:1000,y:430,text:'Cart  \n--------------------------------\n AddtoCart 
  ()\n DeleteFromCart () \n ResetCart () '}
   ];


 var connections = [
 {from:boxes[0], to:boxes[1]},  {from:boxes[1], to:boxes[2]} ];

这是FiddleUML Fiddle

所以我找到了信息框,并查看了他们做了什么:https://github.com/kreynolds/RaphaelJS-Infobox/blob/master/raphaeljs-infobox.js

它有点管用,我希望 Raphael 能帮助解决 SVG 中的 <foreignobject> 元素的问题,但看起来他们并不包含该元素。我以前从未使用过它。所以我可能会进一步研究它,或者看看我是否可以将它注入 paper 另一种方式,这样你就可以得到:

<svg width="500" height="300" style="border:1px red solid">
  <foreignobject class="node" x="46" y="22" width="100" height="100">
    <div style="border:1px green solid">I'm a div inside a SVG.</div>                
  </foreignobject>
</svg>

到目前为止我得到的是:

https://jsfiddle.net/Twisty/pq7p05nc/1/

JavaScript

$(function() {
  // Model
  var boxes = [{
    x: 109,
    y: 120,
    text: 'User  \n--------------------------------\n Login ()\n Signup () \n ViewProduct ()  '
  }, {
    x: 180,
    y: 270,
    text: 'Product  \n--------------------------------\n AddProduct ()\n DeleteProduct () \n UpdateProduct ()  '
  }, {
    x: 370,
    y: 230,
    text: 'Cart  \n--------------------------------\n AddtoCart ()\n DeleteFromCart () \n ResetCart () '
  }];

  var connections = [{
    from: boxes[0],
    to: boxes[1]
  }, {
    from: boxes[1],
    to: boxes[2]
  }];

  // Render
  var paper = new Raphael($('#paper')[0], 700, 500);
  var w = 100;
  var h = 100;

  function redraw() {

    connections.forEach(function(connection) {
      if (typeof connection.view != 'undefined') {
        connection.view.remove();
      }
      connection.view = paper.path(
        'M' + connection.from.x + ',' + connection.from.y + ' ' +
        'L' + connection.to.x + ',' + connection.to.y
      );
      connection.view.toBack();
    });

    var i = 0;
    boxes.forEach(function(box) {
      if (typeof box.view == 'undefined') {
        box.view = {
          rect: paper.rect(-h / 2, -h / 2, w, h),
          text: paper.text(0, 0, box.text)
        };
        box.view.c_id = box.view.rect.node.parentNode.parentNode.id ? box.view.rect.node.parentNode.parentNode.id : box.view.rect.node.parentNode.parentNode.parentNode.id;
        box.view.div_c = $("#" + box.view.c_id);
        box.view.div = $("<div>", {
            id: "ui-box-" + i++,
            class: "dialog-box",
            title: box.text.slice(0, box.text.indexOf("\n"))
          })
          .html(box.text.slice(box.text.indexOf("\n", 12)))
          .appendTo(box.view.div_c)
          .dialog({
            position: {
              my: "left top",
              at: "left+" + box.x + " top+" + box.y,
              of: "#" + box.view.c_id
            },
            width: w,
            height: h + 20
          });
        console.log(box, box.view.div.position());
        box.view.rect.attr({
          //fill: 'lightyellow'
        });
        box.view.rect.drag(function(dx, dy, x, y) {
          box.x = x;
          box.y = y;
        });
      }
      var tbox = 't' + box.x + ',' + box.y;
      box.view.rect.transform(tbox);
      box.view.text.transform(tbox);
    });
  }

  // Controller
  var a = 0;

  function slide() {
    a += 0;
    redraw();
    setTimeout(slide, 10);
  }
  slide();
});

这确实附加了 <div> 并使其成为对话框,但它不在 <svg> 中。我怀疑这不会对您的 drag 事件造成太大问题,但应将它们移动到对话框 drag 回调中以保留 "connections".

这实现了您最初询问的内容,但我怀疑您现在还有更多的兔子洞需要挖掘。

更新 1

固定位置,隐藏关闭按钮,更新拖动:https://jsfiddle.net/Twisty/pq7p05nc/3/

CSS

.dialog-box .ui-dialog-titlebar-close {
  display: none;
}

.dialog-box .ui-dialog-titlebar {
  text-align: center;
  padding: 0.125em;
}

.dialog-box .ui-dialog-content {
  padding: 0.2em;
}

JS

box.view.div = $("<div>", {
  id: "ui-box-" + i++,
  title: box.text.slice(0, box.text.indexOf("\n"))
})
.html(box.text.slice(box.text.indexOf("\n", 12)).replace("/\n/g", "<br />"))
.appendTo(box.view.div_c)
.dialog({
  classes: {
    "ui-dialog": "dialog-box ui-corner-all"
  },
  position: {
    my: "left top",
    at: "left+" + (box.x - (w / 2) - 2) + " top+" + (box.y - (h / 2) - 2),
    of: "#" + box.view.c_id
  },
  width: w,
  height: h,
  drag: function(e, ui) {
    box.x = ui.position.left + (w / 2);
    box.y = ui.position.top + (h / 2);
  }
});

此时您可以禁止创建矩形和文本以隐藏它们。

更新 2

添加了收容并隐藏了 SCG 矩形和文本。

https://jsfiddle.net/Twisty/pq7p05nc/5/

drag: function(e, ui) {
  if (ui.position.left >= $("#paper svg").width() - (w / 2)) {
    ui.position.left = $("#paper svg").width() - (w / 2);
  }
  if (ui.position.top >= $("#paper svg").height() - (h / 2)) {
    ui.position.top = $("#paper svg").height() - (h / 2);
  }
  box.x = ui.position.left + (w / 2);
  box.y = ui.position.top + (h / 2);
}

代码运行良好,谢谢大佬。 @twisty.

我做错了一点。

 var boxes = [{
x: 109,
y: 120,
text: 'User \n--------------------------------\n <a href="asdsad.html" 
style="text-decoration:none">USERID \n<br> Name\n<br> Address\n <hr> Login 
()
<br>Signup ()<br> </a>'
 }, {
x: 180,
y: 270,
 text: 'Product  \n--------------------------------\n ProdID \n<br> 
 Name\n<br> 
  Storeid\n <hr>GetPRoduct()<br>DeleteProduct()<br> ViewProduct ()'
 }, {
  x: 370,
 y: 230,
 text: 'Cart  \n--------------------------------\n Cartid \n<br> Items\n<br> 
 Type\n<br>  <hr> AddProduct()<br>RemoveProduct ()<br> ViewCart ()'  
 }];

 var connections = [{
from: boxes[0],
to: boxes[1]
  }, {
from: boxes[1],
to: boxes[2]
   }];

JS FIDDLE UML Class Diagram 这个link是给那些想用JS生成umlclass图的人。