Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help: VisGraph, focus mode when clicking a node with svelte #453

Open
ab-smith opened this issue Oct 1, 2024 · 1 comment
Open

Help: VisGraph, focus mode when clicking a node with svelte #453

ab-smith opened this issue Oct 1, 2024 · 1 comment

Comments

@ab-smith
Copy link

ab-smith commented Oct 1, 2024

Hello,
I've just started experimenting with the library for some graph related research and looks very promising! I'm using sveltekit and I'm struggling with the events management when clicking on a node as I need it to behave exactly as shown on the online doc (highlight the node and the ones linked to it and reset when clicking away). Feels like I'm missing something simple but I can't put my finger on it. Here's what I've done so far:

<script lang="ts">
	import { VisSingleContainer, VisGraph } from '@unovis/svelte';
	import { GraphLayoutType, GraphNodeShape, Graph } from '@unovis/ts';
	import type { PageData } from './$types';
	export let data: PageData;

	type NodeDatum = {
		id: string;
		label: string;
		color?: string;
		shape?: string;
		counter?: number;
	};

	type LinkDatum = {
		source: string;
		target: string;
		coverage: string;
	};

	type GraphData = {
		nodes: NodeDatum[];
		links: LinkDatum[];
	};

	const nodes: NodeDatum[] = data.data.nodes;
	const links: LinkDatum[] = data.data.links;
	const gdata: GraphData = { nodes, links };

	const linkLabel = (l: LinkDatum) => ({ text: l.coverage });
	const nodeLabel = (n: NodeDatum) => n.label;
	const nodeShape = (n: NodeDatum) => n.shape as GraphNodeShape;
	const nodeStroke = (n: NodeDatum) => n.color;
	const linkFlow = (l: LinkDatum) => l.active;
	const nodeDisabled = (n: NodeDatum, i: number) => n.counter < 1;
	const nodeSideLabels = (n: NodeDatum) => (n.counter ? [{ text: `${n.counter}` }] : []);

	const forceLayoutSettings: GraphForceLayoutSettings = {
		forceXStrength: 0.1,
		forceYStrength: 0.1,
		charge: -800
	};

	let selectedNodeId: string | undefined;

	const handleNodeClick = (node) => {
		selectedNodeId = node.id; // Focus on clicked node
	};

	const handleBackgroundClick = () => {
		selectedNodeId = undefined; // Reset the selection
	};

	const events = {
		[Graph.selectors.node]: {
			click: (node) => handleNodeClick(node)
		},
		[Graph.selectors.background]: {
			click: handleBackgroundClick
		}
	};
</script>

<div class="bg-white p-4">
	<VisSingleContainer data={gdata} height={'60vh'}>
		<VisGraph
			layoutType={GraphLayoutType.Force}
			nodeSize={40}
			{forceLayoutSettings}
			{linkLabel}
			{nodeStroke}
			{nodeLabel}
			{nodeShape}
			{linkFlow}
			{nodeSideLabels}
			{nodeDisabled}
			{events}
			{selectedNodeId}
		/>
	</VisSingleContainer>
</div>

Thank you

@ab-smith ab-smith changed the title Help: VisGraph, focus mode when clicking a node Help: VisGraph, focus mode when clicking a node with svelte Oct 1, 2024
@ab-smith
Copy link
Author

ab-smith commented Oct 1, 2024

The only (ugly) trick that I've found for today is to force resizing the container that helped; in case it can help you guide me here :)

<script lang="ts">
	import { VisSingleContainer, VisGraph } from '@unovis/svelte';
	import { GraphLayoutType, GraphNodeShape, Graph } from '@unovis/ts';
	import type { PageData } from './$types';
	export let data: PageData;

	type NodeDatum = {
		id: string;
		label: string;
		color?: string;
		shape?: string;
		counter?: number;
	};

	type LinkDatum = {
		source: string;
		target: string;
		coverage: string;
		active?: boolean; // Added this property based on usage in linkFlow
	};

	type GraphData = {
		nodes: NodeDatum[];
		links: LinkDatum[];
	};

	const nodes: NodeDatum[] = data.data.nodes;
	const links: LinkDatum[] = data.data.links;
	const gdata: GraphData = { nodes, links };

	const linkLabel = (l: LinkDatum) => ({ text: l.coverage });
	const nodeLabel = (n: NodeDatum) => n.label;
	const nodeShape = (n: NodeDatum) => n.shape as GraphNodeShape;
	const nodeStroke = (n: NodeDatum) => n.color;
	const linkFlow = (l: LinkDatum) => l.active;
	const nodeDisabled = (n: NodeDatum, i: number) => n.counter < 1;
	const nodeSideLabels = (n: NodeDatum) => (n.counter ? [{ text: `${n.counter}` }] : []);

	const forceLayoutSettings = {
		forceXStrength: 0.1,
		forceYStrength: 0.1,
		charge: -800
	};

	let containerHeight = '80vh';
	let selectedNodeId: string | undefined;

	function handleNodeClick(node: NodeDatum) {
		selectedNodeId = node.id;
		// this is ugly but the only trick I've found so far
		containerHeight = '80.1vh';
	}

	function handleBackgroundClick() {
		selectedNodeId = undefined;
		containerHeight = '80vh';
	}

	// Setup events for node and background clicks
	const events = {
		[Graph.selectors.node]: {
			click: handleNodeClick
		},
		[Graph.selectors.background]: {
			click: handleBackgroundClick
		}
	};
</script>

<div class="bg-white p-4 h-full w-full">
	<VisSingleContainer data={gdata} height={containerHeight}>
		<VisGraph
			layoutType={GraphLayoutType.Force}
			nodeSize={40}
			{forceLayoutSettings}
			{linkLabel}
			{nodeStroke}
			{nodeLabel}
			{nodeShape}
			{linkFlow}
			{nodeSideLabels}
			{nodeDisabled}
			{events}
			{selectedNodeId}
		/>
	</VisSingleContainer>
</div>

{#if selectedNodeId}
	<p>Selected Node: {selectedNodeId}</p>
{/if}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant