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
 | 
					  opacityScale: number
 | 
				
			||||||
  removeTags: string[]
 | 
					  removeTags: string[]
 | 
				
			||||||
  showTags: boolean
 | 
					  showTags: boolean
 | 
				
			||||||
 | 
					  focusOnHover?: boolean
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface GraphOptions {
 | 
					interface GraphOptions {
 | 
				
			||||||
@@ -37,6 +38,7 @@ const defaultOptions: GraphOptions = {
 | 
				
			|||||||
    opacityScale: 1,
 | 
					    opacityScale: 1,
 | 
				
			||||||
    showTags: true,
 | 
					    showTags: true,
 | 
				
			||||||
    removeTags: [],
 | 
					    removeTags: [],
 | 
				
			||||||
 | 
					    focusOnHover: false,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  globalGraph: {
 | 
					  globalGraph: {
 | 
				
			||||||
    drag: true,
 | 
					    drag: true,
 | 
				
			||||||
@@ -50,6 +52,7 @@ const defaultOptions: GraphOptions = {
 | 
				
			|||||||
    opacityScale: 1,
 | 
					    opacityScale: 1,
 | 
				
			||||||
    showTags: true,
 | 
					    showTags: true,
 | 
				
			||||||
    removeTags: [],
 | 
					    removeTags: [],
 | 
				
			||||||
 | 
					    focusOnHover: true,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,6 +44,7 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
 | 
				
			|||||||
    opacityScale,
 | 
					    opacityScale,
 | 
				
			||||||
    removeTags,
 | 
					    removeTags,
 | 
				
			||||||
    showTags,
 | 
					    showTags,
 | 
				
			||||||
 | 
					    focusOnHover,
 | 
				
			||||||
  } = JSON.parse(graph.dataset["cfg"]!)
 | 
					  } = JSON.parse(graph.dataset["cfg"]!)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const data: Map<SimpleSlug, ContentDetails> = new Map(
 | 
					  const data: Map<SimpleSlug, ContentDetails> = new Map(
 | 
				
			||||||
@@ -189,6 +190,8 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
 | 
				
			|||||||
    return 2 + Math.sqrt(numLinks)
 | 
					    return 2 + Math.sqrt(numLinks)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let connectedNodes: SimpleSlug[] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // draw individual nodes
 | 
					  // draw individual nodes
 | 
				
			||||||
  const node = graphNode
 | 
					  const node = graphNode
 | 
				
			||||||
    .append("circle")
 | 
					    .append("circle")
 | 
				
			||||||
@@ -202,17 +205,25 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
 | 
				
			|||||||
      window.spaNavigate(new URL(targ, window.location.toString()))
 | 
					      window.spaNavigate(new URL(targ, window.location.toString()))
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    .on("mouseover", function (_, d) {
 | 
					    .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 currentId = d.id
 | 
				
			||||||
      const linkNodes = d3
 | 
					      const linkNodes = d3
 | 
				
			||||||
        .selectAll(".link")
 | 
					        .selectAll(".link")
 | 
				
			||||||
        .filter((d: any) => d.source.id === currentId || d.target.id === currentId)
 | 
					        .filter((d: any) => d.source.id === currentId || d.target.id === currentId)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // highlight neighbour nodes
 | 
					      if (focusOnHover) {
 | 
				
			||||||
      neighbourNodes.transition().duration(200).attr("fill", color)
 | 
					        // 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
 | 
					      // highlight links
 | 
				
			||||||
      linkNodes.transition().duration(200).attr("stroke", "var(--gray)").attr("stroke-width", 1)
 | 
					      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")
 | 
					        .style("font-size", bigFont + "em")
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    .on("mouseleave", function (_, d) {
 | 
					    .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 currentId = d.id
 | 
				
			||||||
      const linkNodes = d3
 | 
					      const linkNodes = d3
 | 
				
			||||||
        .selectAll(".link")
 | 
					        .selectAll(".link")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user