Browse Source

graph: zooming and dragging, changed default repulsion force

mj-deploy
Vašek Šraier 4 years ago
parent
commit
b1dcf45db6
  1. 26
      frontend/src/Editor.svelte
  2. 29
      frontend/src/Graph.svelte
  3. 2
      frontend/src/GraphEdge.svelte
  4. 7
      frontend/src/GraphNode.svelte

26
frontend/src/Editor.svelte

@ -8,10 +8,16 @@
let selectedTask: string | null = null;
let clickedTask: string | null = null;
let repulsionForce: number = -600;
let clicked: string[] = [];
function clickTask(e: CustomEvent<TaskDescriptor>) {
// sanity check
if (selectedTask == null) {
alert("tohle je divny event");
return;
}
// ukladani seznamu poslednich kliknuti
clicked.push(selectedTask);
if (clicked.length > 3)
@ -41,6 +47,9 @@
}
});
tasks = tasks;
// run simulation
toggleDivnaPromena();
} else {
alert("Nope, prvni musis nekam klikat...");
}
@ -48,7 +57,7 @@
let hovnoDivnaPromenaKteraJeFaktFuj = true;
function toggleDivnaPromena() {
hovnoDivnaPromenaKteraJeFaktFuj = ! hovnoDivnaPromenaKteraJeFaktFuj;
hovnoDivnaPromenaKteraJeFaktFuj = !hovnoDivnaPromenaKteraJeFaktFuj;
}
</script>
@ -62,7 +71,7 @@
display: flex;
flex-direction: row;
margin: 0;
height: 100vh;
height: 99vh;
width: 100%;
}
@ -106,7 +115,12 @@
<div class="left">
<div class="lastClicked">Last clicked: <b>{clicked.join(' | ')}</b></div>
<div class="graph">
<Graph {tasks} bind:selectedTask on:selectTask={clickTask} runSimulationWeirdHack={hovnoDivnaPromenaKteraJeFaktFuj} />
<Graph
{tasks}
{repulsionForce}
bind:selectedTask
on:selectTask={clickTask}
runSimulationWeirdHack={hovnoDivnaPromenaKteraJeFaktFuj} />
</div>
</div>
<div class="right">
@ -115,12 +129,14 @@
<div>
<button on:click={addEdge}>Pridat hranu - posledni vyzaduje predposledni</button>
</div>
<div><button on:click={toggleDivnaPromena}>Spustit simulaci</button></div>
<div>
<button on:click={toggleDivnaPromena}>Spustit simulaci</button>
Repulsion force: <input type="number" bind:value={repulsionForce} name="repulsionForceInput" max="1000" min="-10000" />
</div>
</div>
<div class="taskDetails">
{#if currentTask != null}
start
<h3>{currentTask}</h3>
<span>{taskMap.get(currentTask).comment}</span>
<ul>

29
frontend/src/Graph.svelte

@ -10,6 +10,7 @@
export let tasks: TasksFile;
export let selectedTask: null | string = null;
export let repulsionForce: number = -600;
$: nodes = tasks.tasks;
$: edges = createLinksFromTaskMap(tasks);
@ -45,7 +46,7 @@
}) // This provide the id of a node
.links(edges) // and this the list of links
)
.force("charge", d3.forceManyBody().strength(-400)) // This adds repulsion between nodes. Play with the -400 for the repulsion strength
.force("charge", d3.forceManyBody().strength(repulsionForce)) // This adds repulsion between nodes. Play with the -400 for the repulsion strength
.force("x", d3.forceX()) // attracts elements to the zero X coord
.force("y", d3.forceY()) // attracts elements to the zero Y coord
.on("tick", ticked)
@ -61,19 +62,29 @@
// run on create
onMount(() => {
// set the dimensions and margins of the graph
var margin = { top: 10, right: 30, bottom: 30, left: 40 },
width = container.clientWidth - margin.left - margin.right,
height = container.clientHeight - margin.top - margin.bottom;
const width = container.clientWidth;
const height = container.clientHeight;
// resize the svg object
var svg = d3
.select(container)
.select("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("width", width)
.attr("height", height)
.attr("viewBox", [-width / 2, -height / 2, width, height])
.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
.select("g");
function zoomed(e) {
let { transform } = e;
svg.attr("transform", transform);
}
d3.select(container).call(
d3
.zoom()
.scaleExtent([0.1, 2])
.on("zoom", zoomed)
);
runSimulation();
});
@ -85,7 +96,6 @@
runSimulation();
}
// now it's safe to stop vomitting 🤮
</script>
<style>
@ -104,6 +114,7 @@
{#each nodes as task}
<GraphNode
{task}
on:taskClick
on:click={nodeClick(task)}
on:hoveringChange={nodeHover(task)} />
{/each}

2
frontend/src/GraphEdge.svelte

@ -1,7 +1,5 @@
<script lang="ts">
import type { SimulationLinkDatum } from "d3";
import { onMount } from "svelte";
import type { TaskDescriptor } from "./task-loader";

7
frontend/src/GraphNode.svelte

@ -1,17 +1,15 @@
<script lang="ts">
import { createEventDispatcher, onMount } from "svelte";
import type { TaskDescriptor } from "./task-loader";
export let task: TaskDescriptor;
let hovering: boolean = false;
let text_element: SVGTextElement;
const eventDispatcher = createEventDispatcher()
$: cx = task === undefined || task.x === undefined ? 0 : task.x;
$: cy = task === undefined || task.y === undefined ? 0 : task.y;
const eventDispatcher = createEventDispatcher()
function enter() {
hovering = true;
eventDispatcher("hoveringChange", hovering)
@ -26,6 +24,7 @@
eventDispatcher("click", e)
}
// automatically size the bubbles to fit the text
let ellipse_rx = 20;
let ellipse_ry = 20;
onMount(() => {