|
|
|
@ -35,7 +35,7 @@ const node_text_layout = { |
|
|
|
|
fontSize: 22, |
|
|
|
|
width: 2 * node_size - 1, |
|
|
|
|
height: 2 * node_size - 1, |
|
|
|
|
fontFamily: 'Roboto', |
|
|
|
|
fontFamily: 'Roboto, Arial, Verdana, sans-serif', |
|
|
|
|
fill: 'black', |
|
|
|
|
verticalAlign: 'middle', |
|
|
|
|
align: 'center' |
|
|
|
@ -50,7 +50,7 @@ const edge_text_layout = { |
|
|
|
|
fontSize: 22, |
|
|
|
|
width: 2 * node_size, |
|
|
|
|
height: 2 * node_size, |
|
|
|
|
fontFamily: 'Roboto', |
|
|
|
|
fontFamily: 'Roboto, Arial, Verdana, sans-serif', |
|
|
|
|
fill: 'black', |
|
|
|
|
verticalAlign: 'middle', |
|
|
|
|
align: 'center' |
|
|
|
@ -103,10 +103,10 @@ function initialization() { |
|
|
|
|
for (var i = 0; i < 1000; i++) { |
|
|
|
|
force_directed_graph(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
edge_layer.show(); |
|
|
|
|
node_layer.draw(); |
|
|
|
|
} |
|
|
|
|
initialization(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
@ -135,6 +135,7 @@ function draw_new_node(name, x, y) { |
|
|
|
|
let group = new Konva.Group({ |
|
|
|
|
x: x, |
|
|
|
|
y: y, |
|
|
|
|
dragDistance: 5, |
|
|
|
|
draggable: true, |
|
|
|
|
dragBoundFunc: function(pos) { |
|
|
|
|
return { |
|
|
|
@ -186,7 +187,7 @@ function draw_new_edge(edge) { |
|
|
|
|
let line = new Konva.Line(edge_layout); |
|
|
|
|
let simpleText = new Konva.Text({ |
|
|
|
|
...edge_text_layout, |
|
|
|
|
text: weight |
|
|
|
|
text: ""+weight |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
graph_copy[edge["start"]].push(edge["end"]); |
|
|
|
@ -237,7 +238,7 @@ function draw_selected_nodes() { |
|
|
|
|
reset_node_style(); |
|
|
|
|
reset_edge_style(); |
|
|
|
|
for (let id in selected) { |
|
|
|
|
selected[id].children[0].strokeWidth(node_layout.strokeWidth + 1); |
|
|
|
|
selected[id].children[0].strokeWidth(node_layout.strokeWidth+1); |
|
|
|
|
selected[id].children[0].stroke("rgb(240, 141, 25)"); |
|
|
|
|
} |
|
|
|
|
node_layer.draw(); |
|
|
|
@ -298,8 +299,8 @@ function create_node() { |
|
|
|
|
state = "create_node"; |
|
|
|
|
// let mousePos = stage.getPointerPosition();
|
|
|
|
|
let pos = { |
|
|
|
|
x: width / 2, |
|
|
|
|
y: height / 2 |
|
|
|
|
x: (Math.random()-0.5)*node_size*4+width / 2, |
|
|
|
|
y: (Math.random()-0.5)*node_size*4+height / 2 |
|
|
|
|
}; |
|
|
|
|
create_input(pos.x, pos.y).then(function(text) { |
|
|
|
|
post("nodes", { |
|
|
|
@ -387,7 +388,6 @@ function find_path(data) { |
|
|
|
|
show_error("Select at least 2 nodes."); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
console.log(url + "paths/" + data[0].attrs.id + "/" + data[1].attrs.id); |
|
|
|
|
fetch(url + "paths/" + data[0].attrs.id + "/" + data[1].attrs.id).then(res => res.json()) |
|
|
|
|
.then(function(res) { |
|
|
|
|
if (res["error"]) { |
|
|
|
@ -434,6 +434,9 @@ function toggle_auto_layout() { |
|
|
|
|
|
|
|
|
|
function normalize(vec) { |
|
|
|
|
let l = Math.sqrt(vec[0] ** 2 + vec[1] ** 2); |
|
|
|
|
if (l == 0){ |
|
|
|
|
return [vec[0], vec[1]]; |
|
|
|
|
} |
|
|
|
|
return [vec[0] / l, vec[1] / l]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -463,16 +466,21 @@ function force_directed_graph(spring_length = 300, step = 0.004) { |
|
|
|
|
let x2 = konva_nodes[jdx].getX(); |
|
|
|
|
let y2 = konva_nodes[jdx].getY(); |
|
|
|
|
let dir = normalize([x2 - x1, y2 - y1]); |
|
|
|
|
let dist = ((x1 - x2) ** 2 + (y1 - y2) ** 2); |
|
|
|
|
let dist = Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2); |
|
|
|
|
if (dist == 0){ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (in_edges(konva_nodes[idx], konva_nodes[jdx])) { |
|
|
|
|
let f = (dist / spring_length); |
|
|
|
|
let f = (dist**2 / spring_length); |
|
|
|
|
attr[0] += f * dir[0]; |
|
|
|
|
attr[1] += f * dir[1]; |
|
|
|
|
} |
|
|
|
|
let f = (spring_length ** 2 / Math.sqrt(dist)); |
|
|
|
|
if (dist < width*0.4){ |
|
|
|
|
let f = (spring_length ** 2 / dist); |
|
|
|
|
rep[0] -= f * dir[0]; |
|
|
|
|
rep[1] -= f * dir[1]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
let new_x = x1 + step * (rep[0] + attr[0]); |
|
|
|
|
let new_y = y1 + step * (rep[1] + attr[1]); |
|
|
|
|
if (new_x < 2 * node_size) { |
|
|
|
@ -493,11 +501,14 @@ function force_directed_graph(spring_length = 300, step = 0.004) { |
|
|
|
|
var anim = new Konva.Animation(function(frame) { |
|
|
|
|
if (auto_layout && focus) { |
|
|
|
|
const step = 0.00025 * frame.timeDiff; |
|
|
|
|
force_directed_graph(300, step) |
|
|
|
|
let spring_factor = Math.min((konva_edges.length+konva_nodes.length-3)/20, 1); |
|
|
|
|
force_directed_graph(150+(1-spring_factor)*180, step); |
|
|
|
|
} |
|
|
|
|
}, node_layer); |
|
|
|
|
anim.start(); |
|
|
|
|
|
|
|
|
|
initialization(); |
|
|
|
|
|
|
|
|
|
// bug: this avoids glitches
|
|
|
|
|
window.onfocus = function() {focus = true;}; |
|
|
|
|
window.onblur = function() {focus = false;}; |
|
|
|
|