Skip to content

Commit 5bdf9d8

Browse files
committed
add graph
1 parent c90d014 commit 5bdf9d8

File tree

6 files changed

+383
-0
lines changed

6 files changed

+383
-0
lines changed

app/(public)/sample/page.jsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use client"
2+
3+
import React, { useEffect, useState } from "react"
4+
import Tree from "./tree"
5+
6+
export default function Page() {
7+
const [data, setData] = useState([])
8+
9+
useEffect(() => {
10+
fetch("/data/flare-2.json")
11+
.then((res) => res.json())
12+
.then((data) => setData(data))
13+
}, [])
14+
15+
return (
16+
<div>
17+
<h1 className="mt-2 text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100">Evaluation Result</h1>
18+
<Tree data={data} />
19+
</div>
20+
)
21+
}

app/(public)/sample/tree.jsx

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"use client"
2+
3+
import { useEffect, useRef } from "react"
4+
import * as d3 from "d3"
5+
6+
export default function Tree({ data }) {
7+
const svgRef = useRef(null)
8+
9+
useEffect(() => {
10+
if (!data) return
11+
12+
const width = 928
13+
const height = 600
14+
15+
d3.select(svgRef.current).selectAll("*").remove()
16+
17+
const root = d3.hierarchy(data)
18+
const links = root.links()
19+
const nodes = root.descendants()
20+
21+
const simulation = d3
22+
.forceSimulation(nodes)
23+
.force(
24+
"link",
25+
d3
26+
.forceLink(links)
27+
.id((d) => d.id)
28+
.distance(0)
29+
.strength(1)
30+
)
31+
.force("charge", d3.forceManyBody().strength(-50))
32+
.force("x", d3.forceX())
33+
.force("y", d3.forceY())
34+
35+
const svg = d3
36+
.select(svgRef.current)
37+
.attr("width", width)
38+
.attr("height", height)
39+
.attr("viewBox", [-width / 2, -height / 2, width, height])
40+
.style("max-width", "100%")
41+
.style("height", "auto")
42+
43+
function drag(simulation) {
44+
function dragstarted(event, d) {
45+
if (!event.active) simulation.alphaTarget(0.3).restart()
46+
d.fx = d.x
47+
d.fy = d.y
48+
}
49+
function dragged(event, d) {
50+
d.fx = event.x
51+
d.fy = event.y
52+
}
53+
function dragended(event, d) {
54+
if (!event.active) simulation.alphaTarget(0)
55+
d.fx = null
56+
d.fy = null
57+
}
58+
return d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended)
59+
}
60+
61+
const link = svg.append("g").attr("stroke", "#999").attr("stroke-opacity", 0.6).selectAll("line").data(links).join("line")
62+
63+
const node = svg
64+
.append("g")
65+
.attr("fill", "#fff")
66+
.attr("stroke", "#000")
67+
.attr("stroke-width", 1.5)
68+
.selectAll("circle")
69+
.data(nodes)
70+
.join("circle")
71+
.attr("fill", (d) => (d.children ? null : "#000"))
72+
.attr("stroke", (d) => (d.children ? null : "#fff"))
73+
.attr("r", 3.5)
74+
.call(drag(simulation))
75+
76+
// NEW: labels for each node
77+
const labels = svg
78+
.append("g")
79+
.attr("font-family", "sans-serif")
80+
.attr("font-size", 10)
81+
.attr("fill", "#333")
82+
.selectAll("text")
83+
.data(nodes)
84+
.join("text")
85+
.text((d) => d.data.name)
86+
.attr("text-anchor", "middle")
87+
.attr("dy", -6) // position above the circle
88+
89+
node.append("title").text((d) => d.data.name)
90+
91+
simulation.on("tick", () => {
92+
link
93+
.attr("x1", (d) => d.source.x)
94+
.attr("y1", (d) => d.source.y)
95+
.attr("x2", (d) => d.target.x)
96+
.attr("y2", (d) => d.target.y)
97+
98+
node.attr("cx", (d) => d.x).attr("cy", (d) => d.y)
99+
100+
labels.attr("x", (d) => d.x).attr("y", (d) => d.y - 8)
101+
})
102+
103+
return () => simulation.stop()
104+
}, [data])
105+
106+
return <svg ref={svgRef}></svg>
107+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"use client"
2+
3+
import { useEffect, useRef } from "react"
4+
import * as d3 from "d3"
5+
6+
export default function Hierarchy({ data }) {
7+
const svgRef = useRef(null)
8+
9+
useEffect(() => {
10+
if (!data) return
11+
12+
const width = 928
13+
const height = 600
14+
15+
d3.select(svgRef.current).selectAll("*").remove()
16+
17+
const root = d3.hierarchy(data)
18+
const links = root.links()
19+
const nodes = root.descendants()
20+
21+
const simulation = d3
22+
.forceSimulation(nodes)
23+
.force(
24+
"link",
25+
d3
26+
.forceLink(links)
27+
.id((d) => d.id)
28+
.distance(0)
29+
.strength(1)
30+
)
31+
.force("charge", d3.forceManyBody().strength(-50))
32+
.force("x", d3.forceX())
33+
.force("y", d3.forceY())
34+
35+
const svg = d3
36+
.select(svgRef.current)
37+
.attr("width", width)
38+
.attr("height", height)
39+
.attr("viewBox", [-width / 2, -height / 2, width, height])
40+
.style("max-width", "100%")
41+
.style("height", "auto")
42+
43+
function drag(simulation) {
44+
function dragstarted(event, d) {
45+
if (!event.active) simulation.alphaTarget(0.3).restart()
46+
d.fx = d.x
47+
d.fy = d.y
48+
}
49+
function dragged(event, d) {
50+
d.fx = event.x
51+
d.fy = event.y
52+
}
53+
function dragended(event, d) {
54+
if (!event.active) simulation.alphaTarget(0)
55+
d.fx = null
56+
d.fy = null
57+
}
58+
return d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended)
59+
}
60+
61+
const link = svg.append("g").attr("stroke", "#999").attr("stroke-opacity", 0.6).selectAll("line").data(links).join("line")
62+
63+
const node = svg
64+
.append("g")
65+
.attr("fill", "#fff")
66+
.attr("stroke", "#000")
67+
.attr("stroke-width", 1.5)
68+
.selectAll("circle")
69+
.data(nodes)
70+
.join("circle")
71+
.attr("fill", (d) => (d.children ? null : "#000"))
72+
.attr("stroke", (d) => (d.children ? null : "#fff"))
73+
.attr("r", 3.5)
74+
.call(drag(simulation))
75+
76+
// NEW: labels for each node
77+
const labels = svg
78+
.append("g")
79+
.attr("font-size", 10)
80+
.attr("fill", "#333")
81+
.selectAll("text")
82+
.data(nodes)
83+
.join("text")
84+
.text((d) => d.data.name)
85+
.attr("text-anchor", "middle")
86+
.attr("dy", -6) // position above the circle
87+
88+
node.append("title").text((d) => d.data.name)
89+
90+
simulation.on("tick", () => {
91+
link
92+
.attr("x1", (d) => d.source.x)
93+
.attr("y1", (d) => d.source.y)
94+
.attr("x2", (d) => d.target.x)
95+
.attr("y2", (d) => d.target.y)
96+
97+
node.attr("cx", (d) => d.x).attr("cy", (d) => d.y)
98+
99+
labels.attr("x", (d) => d.x).attr("y", (d) => d.y - 8)
100+
})
101+
102+
return () => simulation.stop()
103+
}, [data])
104+
105+
return <svg ref={svgRef}></svg>
106+
}

app/(taxonomy)/hierarchy/page.jsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use client"
2+
3+
import React, { useEffect, useState } from "react"
4+
import Hierarchy from "./hierarchy.jsx"
5+
6+
export default function Page() {
7+
const [data, setData] = useState([])
8+
9+
useEffect(() => {
10+
fetch("/data/flare-2.json")
11+
.then((res) => res.json())
12+
.then((data) => setData(data))
13+
}, [])
14+
15+
return (
16+
<div>
17+
<h1 className="mt-2 text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100">Evaluation Result</h1>
18+
<Hierarchy data={data} />
19+
</div>
20+
)
21+
}

app/(taxonomy)/taxonomy/page.jsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use client"
2+
3+
import React, { useEffect, useState } from "react"
4+
import Taxonomy from "./toxonomy"
5+
6+
export default function Page() {
7+
const [data, setData] = useState([])
8+
9+
useEffect(() => {
10+
fetch("/data/flare-2.json")
11+
.then((res) => res.json())
12+
.then((data) => setData(data))
13+
}, [])
14+
15+
return (
16+
<div>
17+
<h1 className="mt-2 text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100">Evaluation Result (This page could be change)</h1>
18+
<Taxonomy data={data} />
19+
</div>
20+
)
21+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"use client"
2+
3+
import { useEffect, useRef } from "react"
4+
import * as d3 from "d3"
5+
6+
export default function Taxonomy({ data }) {
7+
const svgRef = useRef(null)
8+
9+
useEffect(() => {
10+
if (!data) return
11+
12+
const width = 928
13+
const height = 600
14+
15+
d3.select(svgRef.current).selectAll("*").remove()
16+
17+
const root = d3.hierarchy(data)
18+
const links = root.links()
19+
const nodes = root.descendants()
20+
21+
const simulation = d3
22+
.forceSimulation(nodes)
23+
.force(
24+
"link",
25+
d3
26+
.forceLink(links)
27+
.id((d) => d.id)
28+
.distance(0)
29+
.strength(1)
30+
)
31+
.force("charge", d3.forceManyBody().strength(-50))
32+
.force("x", d3.forceX())
33+
.force("y", d3.forceY())
34+
35+
const svg = d3
36+
.select(svgRef.current)
37+
.attr("width", width)
38+
.attr("height", height)
39+
.attr("viewBox", [-width / 2, -height / 2, width, height])
40+
.style("max-width", "100%")
41+
.style("height", "auto")
42+
43+
function drag(simulation) {
44+
function dragstarted(event, d) {
45+
if (!event.active) simulation.alphaTarget(0.3).restart()
46+
d.fx = d.x
47+
d.fy = d.y
48+
}
49+
function dragged(event, d) {
50+
d.fx = event.x
51+
d.fy = event.y
52+
}
53+
function dragended(event, d) {
54+
if (!event.active) simulation.alphaTarget(0)
55+
d.fx = null
56+
d.fy = null
57+
}
58+
return d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended)
59+
}
60+
61+
const link = svg.append("g").attr("stroke", "#999").attr("stroke-opacity", 0.6).selectAll("line").data(links).join("line")
62+
63+
const node = svg
64+
.append("g")
65+
.attr("fill", "#fff")
66+
.attr("stroke", "#000")
67+
.attr("stroke-width", 1.5)
68+
.selectAll("circle")
69+
.data(nodes)
70+
.join("circle")
71+
.attr("fill", (d) => (d.children ? null : "#000"))
72+
.attr("stroke", (d) => (d.children ? null : "#fff"))
73+
.attr("r", 3.5)
74+
.call(drag(simulation))
75+
76+
// NEW: labels for each node
77+
const labels = svg
78+
.append("g")
79+
.attr("font-family", "sans-serif")
80+
.attr("font-size", 10)
81+
.attr("fill", "#333")
82+
.selectAll("text")
83+
.data(nodes)
84+
.join("text")
85+
.text((d) => d.data.name)
86+
.attr("text-anchor", "middle")
87+
.attr("dy", -6) // position above the circle
88+
89+
node.append("title").text((d) => d.data.name)
90+
91+
simulation.on("tick", () => {
92+
link
93+
.attr("x1", (d) => d.source.x)
94+
.attr("y1", (d) => d.source.y)
95+
.attr("x2", (d) => d.target.x)
96+
.attr("y2", (d) => d.target.y)
97+
98+
node.attr("cx", (d) => d.x).attr("cy", (d) => d.y)
99+
100+
labels.attr("x", (d) => d.x).attr("y", (d) => d.y - 8)
101+
})
102+
103+
return () => simulation.stop()
104+
}, [data])
105+
106+
return <svg ref={svgRef}></svg>
107+
}

0 commit comments

Comments
 (0)