JSFiddle - React, Tailwind, and code Playground

by eprouver

HTML

<input type="range" min="0" max="1000" oninput="changeval('x', this)" value="400"/>
<input type="range" min="0" max="1000" oninput="changeval('y', this)" value="400"/>
<input type="range" min="1" max="1000" oninput="changeval('z', this)" value="100"/>

CSS

.node {
  stroke: #fff;
  stroke-width: 1.5px;
}

JavaScript

var dirs = {
    x: 400,
    y: 400,
    z: 100
};

function changeval(d, v){
    dirs[d] = v.value;
svg.attr('viewBox', [dirs.x, dirs.y, parseInt(dirs.x)+parseInt(dirs.z), parseInt(dirs.y)+parseInt(dirs.z)].join(' '));
}

var width = 1000,
    height = 1000;

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

var svg = d3.select("body").append("svg")
.attr('id', 'mysvg')
    .attr("width", width)
    .attr("height", height)
.attr('viewBox', '400 400 500 500')

var graph = {
    nodes: [{
        "name": "Myriel",
        "group": 1
    }],
    links: []
}

force.nodes(graph.nodes)
    .links(graph.links)
    .start();

var link = svg.selectAll(".link")
    .data(graph.links)
    .enter().append("line")
    .attr("class", "link")
    .style("stroke-width", function (d) {
    return Math.sqrt(d.value);
});

var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("circle")
    .attr("class", "node")
    .attr("r", 5)
    .style("fill", function (d) {
    return color(d.group);
})
    .call(force.drag);


force.on("tick", function () {
    link.attr("x1", function (d) {
        return d.source.x;
    })
        .attr("y1", function (d) {
        return d.source.y;
    })
        .attr("x2", function (d) {
        return d.target.x;
    })
        .attr("y2", function (d) {
        return d.target.y;
    });

    node.attr("cx", function (d) {
        return d.x;
    })
        .attr("cy", function (d) {
        return d.y;
    });
});

function addNode() {
    force.stop();
    
    graph.nodes.push({
        "name": 'test',
        "group": ~~(Math.random() * 50)
    });
    graph.links.push({
        "source": graph.nodes.length - 1,
        'target': ~~(Math.random() * graph.nodes.length),
        "value": 1
    });
    
    node = svg.selectAll(".node")
        .data(graph.nodes)
        .enter().append("circle")
        .attr("class", "node")
       ...