mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-12 12:20:23 +01:00
Pull nodes towards dragged node (#158)
Co-authored-by: Damian Tarnawski <gthetarnav@gmail.com>
This commit is contained in:
@@ -110,27 +110,30 @@ const TITLE_SIZE_PX = 400
|
|||||||
|
|
||||||
const simulateGraph = (
|
const simulateGraph = (
|
||||||
alpha: number,
|
alpha: number,
|
||||||
graph: fg.graph.Graph,
|
gestures: fg.canvas.CanvasGestures,
|
||||||
canvas: fg.canvas.CanvasState,
|
|
||||||
vw: number,
|
vw: number,
|
||||||
vh: number
|
vh: number
|
||||||
): void => {
|
): void => {
|
||||||
|
let c = gestures.canvas
|
||||||
|
let g = c.graph
|
||||||
|
|
||||||
alpha = alpha / 10 // slow things down a bit
|
alpha = alpha / 10 // slow things down a bit
|
||||||
|
|
||||||
fg.graph.simulate(graph, alpha)
|
fg.graph.simulate(g, alpha)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Push nodes away from the center (the title)
|
Push nodes away from the center (the title)
|
||||||
*/
|
*/
|
||||||
let grid_radius = graph.options.grid_size / 2
|
let grid_radius = g.options.grid_size / 2
|
||||||
let origin_x = grid_radius + canvas.translate.x
|
let origin_x = grid_radius + c.translate.x
|
||||||
let origin_y = grid_radius + canvas.translate.y
|
let origin_y = grid_radius + c.translate.y
|
||||||
let vmax = Math.max(vw, vh)
|
let vmax = Math.max(vw, vh)
|
||||||
let push_radius =
|
let push_radius =
|
||||||
(Math.min(TITLE_SIZE_PX, vw / 2, vh / 2) / vmax) * (graph.options.grid_size / canvas.scale) +
|
(Math.min(TITLE_SIZE_PX, vw / 2, vh / 2) / vmax) * (g.options.grid_size / c.scale) +
|
||||||
80 /* additional margin for when scrolled in */
|
80 /* additional margin for when scrolled in */
|
||||||
|
|
||||||
for (let node of graph.nodes) {
|
for (let node of g.nodes) {
|
||||||
|
//
|
||||||
let dist_x = node.pos.x - origin_x
|
let dist_x = node.pos.x - origin_x
|
||||||
let dist_y = (node.pos.y - origin_y) * 2
|
let dist_y = (node.pos.y - origin_y) * 2
|
||||||
let dist = Math.sqrt(dist_x * dist_x + dist_y * dist_y)
|
let dist = Math.sqrt(dist_x * dist_x + dist_y * dist_y)
|
||||||
@@ -141,6 +144,25 @@ const simulateGraph = (
|
|||||||
node.vel.x += strength * (node.pos.x - origin_x) * 10 * alpha
|
node.vel.x += strength * (node.pos.x - origin_x) * 10 * alpha
|
||||||
node.vel.y += strength * (node.pos.y - origin_y) * 10 * alpha
|
node.vel.y += strength * (node.pos.y - origin_y) * 10 * alpha
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
When a node is being dragged
|
||||||
|
it will pull it's connections
|
||||||
|
*/
|
||||||
|
if (gestures.mode.type === fg.canvas.Mode.DraggingNode) {
|
||||||
|
//
|
||||||
|
let node = gestures.mode.node
|
||||||
|
|
||||||
|
for (let edge of fg.graph.each_node_edge(g, node)) {
|
||||||
|
let b = edge.b === node ? edge.a : edge.b
|
||||||
|
|
||||||
|
let dx = (b.pos.x - node.pos.x) * g.options.link_strength * edge.strength * alpha * 10
|
||||||
|
let dy = (b.pos.y - node.pos.y) * g.options.link_strength * edge.strength * alpha * 10
|
||||||
|
|
||||||
|
b.vel.x -= dx / b.mass
|
||||||
|
b.vel.y -= dy / b.mass
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const drawGraph = (c: fg.canvas.CanvasState, color_map: ColorMap): void => {
|
const drawGraph = (c: fg.canvas.CanvasState, color_map: ColorMap): void => {
|
||||||
@@ -230,32 +252,6 @@ function init(
|
|||||||
init_grid_pos: trig.ZERO
|
init_grid_pos: trig.ZERO
|
||||||
})
|
})
|
||||||
|
|
||||||
s.ro = new ResizeObserver(() => {
|
|
||||||
if (canvas.resizeCanvasToDisplaySize(canvas_el)) {
|
|
||||||
fg.canvas.updateTranslate(canvas_state, canvas_state.translate.x, canvas_state.translate.y)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
s.ro.observe(canvas_el)
|
|
||||||
|
|
||||||
simulateGraph(6, s.graph, canvas_state, window.innerWidth, window.innerHeight)
|
|
||||||
|
|
||||||
function loop(time: number) {
|
|
||||||
let is_active = gestures.mode.type === fg.canvas.Mode.DraggingNode
|
|
||||||
let iterations = Math.min(2, raf.calcIterations(s.frame_iter_limit, time))
|
|
||||||
|
|
||||||
for (let i = iterations; i > 0; i--) {
|
|
||||||
s.alpha = raf.updateAlpha(s.alpha, is_active || time < s.bump_end)
|
|
||||||
simulateGraph(s.alpha, s.graph, canvas_state, window.innerWidth, window.innerHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iterations > 0) {
|
|
||||||
drawGraph(canvas_state, color_map)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.raf_id = requestAnimationFrame(loop)
|
|
||||||
}
|
|
||||||
s.raf_id = requestAnimationFrame(loop)
|
|
||||||
|
|
||||||
let gestures = (s.gestures = fg.canvas.canvasGestures({
|
let gestures = (s.gestures = fg.canvas.canvasGestures({
|
||||||
canvas: canvas_state,
|
canvas: canvas_state,
|
||||||
onGesture: e => {
|
onGesture: e => {
|
||||||
@@ -272,6 +268,34 @@ function init(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
s.ro = new ResizeObserver(() => {
|
||||||
|
if (canvas.resizeCanvasToDisplaySize(canvas_el)) {
|
||||||
|
fg.canvas.updateTranslate(canvas_state, canvas_state.translate.x, canvas_state.translate.y)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
s.ro.observe(canvas_el)
|
||||||
|
|
||||||
|
// initial simulation is the most crazy
|
||||||
|
// so it's off-screen
|
||||||
|
simulateGraph(6, gestures, window.innerWidth, window.innerHeight)
|
||||||
|
|
||||||
|
function loop(time: number) {
|
||||||
|
let is_active = gestures.mode.type === fg.canvas.Mode.DraggingNode
|
||||||
|
let iterations = Math.min(2, raf.calcIterations(s.frame_iter_limit, time))
|
||||||
|
|
||||||
|
for (let i = iterations; i > 0; i--) {
|
||||||
|
s.alpha = raf.updateAlpha(s.alpha, is_active || time < s.bump_end)
|
||||||
|
simulateGraph(s.alpha, gestures, window.innerWidth, window.innerHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iterations > 0) {
|
||||||
|
drawGraph(canvas_state, color_map)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.raf_id = requestAnimationFrame(loop)
|
||||||
|
}
|
||||||
|
s.raf_id = requestAnimationFrame(loop)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateQuery(s: State, filter_query: string) {
|
function updateQuery(s: State, filter_query: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user