feat(graph): focusOnHover (#954)
by default, globalGraph will enable focusOnHover, similar to Obsidian. --------- Signed-off-by: Aaron <29749331+aarnphm@users.noreply.github.com>
This commit is contained in:
		| @@ -17,6 +17,7 @@ export interface D3Config { | ||||
|   opacityScale: number | ||||
|   removeTags: string[] | ||||
|   showTags: boolean | ||||
|   focusOnHover?: boolean | ||||
| } | ||||
|  | ||||
| interface GraphOptions { | ||||
| @@ -37,6 +38,7 @@ const defaultOptions: GraphOptions = { | ||||
|     opacityScale: 1, | ||||
|     showTags: true, | ||||
|     removeTags: [], | ||||
|     focusOnHover: false, | ||||
|   }, | ||||
|   globalGraph: { | ||||
|     drag: true, | ||||
| @@ -50,6 +52,7 @@ const defaultOptions: GraphOptions = { | ||||
|     opacityScale: 1, | ||||
|     showTags: true, | ||||
|     removeTags: [], | ||||
|     focusOnHover: true, | ||||
|   }, | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -44,6 +44,7 @@ async function renderGraph(container: string, fullSlug: FullSlug) { | ||||
|     opacityScale, | ||||
|     removeTags, | ||||
|     showTags, | ||||
|     focusOnHover, | ||||
|   } = JSON.parse(graph.dataset["cfg"]!) | ||||
|  | ||||
|   const data: Map<SimpleSlug, ContentDetails> = new Map( | ||||
| @@ -189,6 +190,8 @@ async function renderGraph(container: string, fullSlug: FullSlug) { | ||||
|     return 2 + Math.sqrt(numLinks) | ||||
|   } | ||||
|  | ||||
|   let connectedNodes: SimpleSlug[] = [] | ||||
|  | ||||
|   // draw individual nodes | ||||
|   const node = graphNode | ||||
|     .append("circle") | ||||
| @@ -202,17 +205,25 @@ async function renderGraph(container: string, fullSlug: FullSlug) { | ||||
|       window.spaNavigate(new URL(targ, window.location.toString())) | ||||
|     }) | ||||
|     .on("mouseover", function (_, d) { | ||||
|       const neighbours: SimpleSlug[] = data.get(slug)?.links ?? [] | ||||
|       const neighbourNodes = d3 | ||||
|         .selectAll<HTMLElement, NodeData>(".node") | ||||
|         .filter((d) => neighbours.includes(d.id)) | ||||
|       const currentId = d.id | ||||
|       const linkNodes = d3 | ||||
|         .selectAll(".link") | ||||
|         .filter((d: any) => d.source.id === currentId || d.target.id === currentId) | ||||
|  | ||||
|       // highlight neighbour nodes | ||||
|       neighbourNodes.transition().duration(200).attr("fill", color) | ||||
|       if (focusOnHover) { | ||||
|         // fade out non-neighbour nodes | ||||
|         connectedNodes = linkNodes.data().flatMap((d: any) => [d.source.id, d.target.id]) | ||||
|  | ||||
|         d3.selectAll<HTMLElement, NodeData>(".link") | ||||
|           .transition() | ||||
|           .duration(200) | ||||
|           .style("opacity", 0.2) | ||||
|         d3.selectAll<HTMLElement, NodeData>(".node") | ||||
|           .filter((d) => !connectedNodes.includes(d.id)) | ||||
|           .transition() | ||||
|           .duration(200) | ||||
|           .style("opacity", 0.2) | ||||
|       } | ||||
|  | ||||
|       // highlight links | ||||
|       linkNodes.transition().duration(200).attr("stroke", "var(--gray)").attr("stroke-width", 1) | ||||
| @@ -231,6 +242,10 @@ async function renderGraph(container: string, fullSlug: FullSlug) { | ||||
|         .style("font-size", bigFont + "em") | ||||
|     }) | ||||
|     .on("mouseleave", function (_, d) { | ||||
|       if (focusOnHover) { | ||||
|         d3.selectAll<HTMLElement, NodeData>(".link").transition().duration(200).style("opacity", 1) | ||||
|         d3.selectAll<HTMLElement, NodeData>(".node").transition().duration(200).style("opacity", 1) | ||||
|       } | ||||
|       const currentId = d.id | ||||
|       const linkNodes = d3 | ||||
|         .selectAll(".link") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user