JSFiddle - React, Tailwind, and code Playground
by eprouver
HTML
<div id="display"></div>
CSS
.node {
fill: #007fff;
stroke: #000;
cursor: crosshair;
}
.node_selected {
fill: #ff7f0e;
stroke: #ff7f0e;
}
.drag_line {
stroke: #999;
stroke-width: 5;
pointer-events: none;
}
.drag_line_hidden {
stroke: #999;
stroke-width: 0;
pointer-events: none;
}
.link {
stroke: #999;
stroke-width: 5;
cursor: crosshair;
}
.link_selected {
stroke: #ff7f0e;
}
JavaScript
var width = 300,
height = 500,
fill = d3.scale.category20();
// mouse event vars
var selected_node = null,
selected_link = null,
mousedown_link = null,
mousedown_node = null,
mouseup_node = null;
d3.selectAll('svg').remove();
// init svg
var outer = d3.select("#display")
.append("svg:svg")
.attr("width", width)
.attr("height", height)
.attr("pointer-events", "all");
var vis = outer.append('svg:g')
.on("mousemove", mousemove)
.on("mouseup", mouseup);
vis.append('svg:rect')
.attr('width', width)
.attr('height', height)
.attr('fill', 'white');
// init force layout
var force = d3.layout.force()
.size([width, height])
.nodes([{}, {}, {}]) // initialize with a single node
.linkDistance(100)
.charge(-500)
.on("tick", tick);
// line displayed when dragging new nodes
var drag_line = vis.append("line")
.attr("class", "drag_line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 0)
.attr("y2", 0);
// get layout properties
var nodes = force.nodes(),
links = force.links(),
node = vis.selectAll(".node"),
link = vis.selectAll(".link");
// add keyboard callback
d3.select(window)
.on("keydown", keydown);
redraw();
function mousemove() {
if (!mousedown_node) return;
// update drag line
drag_line.attr("x1", mousedown_node.x)
.attr("y1", mousedown_node.y)
.attr("x2", d3.mouse(this)[0])
.attr("y2", d3.mouse(this)[1]);
}
function mouseup() {
if (mousedown_node) {
// hide drag line
drag_line.attr("class", "drag_line_hidden")
redraw();
}
// clear mouse event vars
resetMouseVars();
}
function resetMouseVars() {
mousedown_node = null;
mouseup_node = null;
mousedown_link = null;
}
function tick() {
link.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return...