JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://use.fontawesome.com/40560117bf.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
JavaScript
var clickedBefore = false;
var coordsOld = [0,0];
$( document ).ready(function() {
var width = $(document).width();
var height = $(document).height()-50;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform);
}))
.append("g");
var viewport = svg.append('g');
//the background for clicking
var background = viewport.append("rect")
.attr("x", -width*50)
.attr("y", -height*50)
.attr("width", width*100)
.attr("height", height*100)
.attr('fill', '#ffffff');
//event listeners
background.on('click', function() {
newNode(viewport, d3.mouse(this));
});
});
function dragstarted(d) {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", "translate(" + d.x + "," + d.y + ")")
//d3.select(this).attr("x", parseFloat(d3.event.x) - parseFloat(this.getBBox().width)/2).attr("y", parseFloat(d3.event.y)-parseFloat(this.getBBox().height)/2);
}
function dragended(d) {
d3.select(this).classed("active", false);
}
function newNode(viewport, coords){
var nodeGroup=viewport.append('g')
.datum({
x: 0,
y: 0
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("mouseover", handleMouseOver)
.on("mouseout", handleMouseOut);
var lineSpace = viewport.append('g');
nodeGroup.append("rect")
.attr("x", coords[0])
.attr("y", coords[1])
.attr('rx', 20)
.attr('ry', 40)
.attr("width", 200)
.attr("height", 40)
.attr('class', 'node');
nodeGroup.append("foreignObject")
.attr("x", coords[0]+12)
.attr("y", coords[1]+10)
.attr("width", 0)
.attr("height", 0)
.append("xhtml:body")
.style("font",...