graph: zooming and dragging, changed default repulsion force
This commit is contained in:
		
							parent
							
								
									2006216a99
								
							
						
					
					
						commit
						b1dcf45db6
					
				
					 4 changed files with 44 additions and 20 deletions
				
			
		|  | @ -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> | ||||
|  |  | |||
|  | @ -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} | ||||
|  |  | |||
|  | @ -1,8 +1,6 @@ | |||
| <script lang="ts"> | ||||
|     import type { SimulationLinkDatum } from "d3"; | ||||
|    | ||||
|     import { onMount } from "svelte"; | ||||
|    | ||||
|     import type { TaskDescriptor } from "./task-loader"; | ||||
|    | ||||
|     export let edge: SimulationLinkDatum<TaskDescriptor>; | ||||
|  |  | |||
|  | @ -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(() => { | ||||
|  |  | |||
		Reference in a new issue