167 lines
3.5 KiB
JavaScript
167 lines
3.5 KiB
JavaScript
|
|
|
|
let input = document.getElementById('select-json');
|
|
let textInput = document.getElementById('text-json');
|
|
let text = document.getElementById('text');
|
|
let simulation;
|
|
let links;
|
|
let nodes;
|
|
let context;
|
|
|
|
textInput.onchange = function change() {
|
|
try {
|
|
json = JSON.parse(this.value);
|
|
nodes = buildNodes(json);
|
|
links = buildLinks(json);
|
|
} catch (e) {
|
|
alert(e.message);
|
|
return;
|
|
}
|
|
render(json);
|
|
}
|
|
|
|
input.onchange = function change() {
|
|
|
|
var reader = new FileReader();
|
|
reader.onload = () => {
|
|
let text = reader.result;
|
|
try {
|
|
json = JSON.parse(text);
|
|
nodes = buildNodes(json);
|
|
links = buildLinks(json);
|
|
} catch (e) {
|
|
alert(e.message);
|
|
return;
|
|
}
|
|
render(json);
|
|
}
|
|
reader.readAsText(this.files[0]);
|
|
};
|
|
|
|
function buildNodes(json) {
|
|
let keys = Object.keys(json);
|
|
return keys.map(key => ({ id: key, group: 1 }));
|
|
}
|
|
|
|
function buildLinks(json) {
|
|
let keys = Object.keys(json);
|
|
let lengths = {};
|
|
keys.forEach(key => lengths[key] = json[key].length);
|
|
return keys.reduce((acc, key) => {
|
|
let list = [];
|
|
json[key].forEach(t => {
|
|
if (keys.indexOf(t) > -1) {
|
|
list.push({ source: key, target: t });
|
|
}
|
|
});
|
|
return acc.concat(list);
|
|
}, []);
|
|
}
|
|
|
|
function render(json) {
|
|
let n = nodes.length;
|
|
text.innerText = `Total of ${n} nodes`;
|
|
let canvas = document.querySelector("canvas");
|
|
|
|
let width = window.innerWidth,
|
|
height = window.innerHeight;
|
|
|
|
context = canvas.getContext("2d");
|
|
d3.select(canvas)
|
|
.attr('width', width * window.devicePixelRatio)
|
|
.attr('height', height * window.devicePixelRatio)
|
|
.style('width', width + 'px')
|
|
.style('height', height + 'px');
|
|
context.scale(window.devicePixelRatio, window.devicePixelRatio);
|
|
|
|
simulation = d3.forceSimulation()
|
|
.force('link', d3.forceLink().id(d => d.id).distance(300))
|
|
.force('charge', d3.forceManyBody())
|
|
.force('center', d3.forceCenter(width / 2, height / 2));
|
|
|
|
simulation.nodes(nodes)
|
|
.on('tick', ticked);
|
|
|
|
simulation.force('link')
|
|
.links(links);
|
|
|
|
d3.select(canvas)
|
|
.call(d3.drag()
|
|
.container(canvas)
|
|
.subject(dragsubject)
|
|
.on('start', dragstarted)
|
|
.on('drag', dragged)
|
|
.on('end', dragended));
|
|
|
|
function ticked() {
|
|
context.clearRect(0, 0, width, height);
|
|
|
|
|
|
links.forEach(drawLink);
|
|
nodes.forEach(drawNode);
|
|
}
|
|
|
|
function dragsubject() {
|
|
return simulation.find(d3.event.x, d3.event.y);
|
|
}
|
|
}
|
|
|
|
function dragstarted() {
|
|
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
|
|
d3.event.subject.fx = d3.event.subject.x;
|
|
d3.event.subject.fy = d3.event.subject.y;
|
|
}
|
|
|
|
function dragged() {
|
|
d3.event.subject.fx = d3.event.x;
|
|
d3.event.subject.fy = d3.event.y;
|
|
}
|
|
|
|
function dragended() {
|
|
if (!d3.event.active) simulation.alphaTarget(0);
|
|
d3.event.subject.fx = null;
|
|
d3.event.subject.fy = null;
|
|
}
|
|
|
|
function drawLink(d) {
|
|
context.beginPath();
|
|
context.moveTo(d.source.x, d.source.y);
|
|
context.lineTo(d.target.x, d.target.y);
|
|
context.lineWidth = 3;
|
|
if (d.target.id === "127.0.0.1" || d.source.id === "127.0.0.1") {
|
|
context.strokeStyle = "red";
|
|
} else if (d.target.id === "127.0.0.2" || d.source.id === "127.0.0.2") {
|
|
context.strokeStyle = "green";
|
|
} else {
|
|
context.strokeStyle = "#aaa";
|
|
}
|
|
context.stroke();
|
|
|
|
}
|
|
|
|
function drawNode(d) {
|
|
context.beginPath();
|
|
context.moveTo(d.x + 10, d.y);
|
|
context.arc(d.x, d.y, 10, 0, 2 * Math.PI);
|
|
context.lineWidth = 1;
|
|
if (d.id === "127.0.0.1") {
|
|
context.fillStyle = "red";
|
|
} else if (d.id === "127.0.0.2" ) {
|
|
context.fillStyle = "green";
|
|
} else {
|
|
context.fillStyle = "black";
|
|
}
|
|
context.fill();
|
|
context.strokeStyle = "#fff";
|
|
context.stroke();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|