Download public/Figure_13.html from latentcanon/code: direct link, hf CLI and curl.
- Browser
- Download file 4.69 kB
-
https://huggingface.co/latentcanon/code/resolve/main/public/Figure_13.html
- Command line
-
hf download hf://latentcanon/code/public/Figure_13.html
-
curl -L -o Figure_13.html https://huggingface.co/latentcanon/code/resolve/main/public/Figure_13.html
4.69 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Danbooru Tree from JSON</title> | |
| <script src="https://d3js.org/d3.v7.min.js"></script> | |
| <style> | |
| body { | |
| font-family: sans-serif; | |
| } | |
| svg { | |
| width: 100%; | |
| height: 1500px; | |
| } | |
| .node circle { | |
| fill: steelblue; | |
| } | |
| .node text { | |
| font-size: 12px; | |
| fill: #333; | |
| } | |
| .link { | |
| fill: none; | |
| stroke: #ccc; | |
| stroke-width: 1.5px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <h2>Danbooru Categories</h2> | |
| <button id="downloadBtn">Download SVG</button> | |
| <svg></svg> | |
| <script> | |
| d3.json("json/danbooru_flat.json").then(function(data) { | |
| const svg = d3.select("svg"); | |
| const width = 750; | |
| const height = 1200; | |
| // ---- STEP 1: Limit second-level children ---- | |
| function limitSecondLevel(node, depth = 0) { | |
| if (node.children && depth === 1 && node.children.length > 5) { | |
| const visible = node.children.slice(0, 5); | |
| visible.push({ name: "...", children: [] }); | |
| node.children = visible; | |
| } | |
| if (node.children) { | |
| node.children.forEach(child => limitSecondLevel(child, depth + 1)); | |
| } | |
| return node; | |
| } | |
| const limited = limitSecondLevel(structuredClone(data)); | |
| const root = d3.hierarchy(limited, d => d.children); | |
| // ---- STEP 2: Track root category for coloring ---- | |
| root.eachAfter(d => { | |
| if (d.depth === 1) { | |
| d.data.rootCategory = d.data.name; | |
| } else if (d.parent) { | |
| d.data.rootCategory = d.parent.data.rootCategory; | |
| } | |
| }); | |
| const treeLayout = d3.tree().size([height, width]); | |
| treeLayout(root); | |
| // ---- STEP 3: Scale for tag_count → radius ---- | |
| const allTagCounts = root.descendants() | |
| .filter(d => d.depth > 0) | |
| .map(d => d.data.tag_count || 0); | |
| const sizeScale = d3.scaleSqrt() | |
| .domain([0, d3.max(allTagCounts)]) | |
| .range([4, 20]); | |
| // ---- STEP 4: Color Map ---- | |
| const categoryColors = { | |
| "attire": "#f4a261", | |
| "body": "#e76f51", | |
| "characters": "#2a9d8f", | |
| "copyrights": "#264653", | |
| "creatures": "#8ecae6", | |
| "drawing software": "#219ebc", | |
| "games": "#3a86ff", | |
| "metatags": "#ffbe0b", | |
| "more": "#b5179e", | |
| "objects": "#6d6875", | |
| "plant": "#7cb518", | |
| "real_world": "#a5a58d", | |
| "sex": "#ef476f", | |
| "visual_characteristics": "#06d6a0", | |
| "subject": "#ffd166", | |
| "uncategorized": "#adb5bd", | |
| "actions_and_expressions": "#d00000", | |
| "objects_and_backgrounds": "#118ab2" | |
| }; | |
| function getColor(d) { | |
| if (d.data.name === "...") return "gray"; | |
| const category = d.data.rootCategory?.toLowerCase(); | |
| return categoryColors[category] || "steelblue"; | |
| } | |
| // ---- STEP 5: Draw Links ---- | |
| svg.selectAll(".link") | |
| .data(root.links()) | |
| .join("path") | |
| .attr("class", "link") | |
| .attr("d", d3.linkHorizontal() | |
| .x(d => d.y) | |
| .y(d => d.x) | |
| ); | |
| // ---- STEP 6: Draw Nodes ---- | |
| const node = svg.selectAll(".node") | |
| .data(root.descendants()) | |
| .join("g") | |
| .attr("class", "node") | |
| .attr("transform", d => `translate(${d.y},${d.x})`); | |
| node.append("circle") | |
| .attr("r", d => d.depth === 0 ? 6 : sizeScale(d.data.tag_count || 0)) | |
| .style("fill", d => d.data.color || "steelblue"); | |
| node.append("title") | |
| .text(d => `${d.data.name}\nTags: ${d.data.tag_count || 0}`); | |
| node.append("text") | |
| .attr("x", 10) | |
| .style("font-weight", "bold") | |
| .attr("dy", "0.32em") | |
| .text(d => d.data.name); | |
| }); | |
| document.getElementById("downloadBtn").addEventListener("click", () => { | |
| const svgNode = document.querySelector("svg"); | |
| // Clone the SVG node to preserve original | |
| const clonedSvg = svgNode.cloneNode(true); | |
| const outer = document.createElement("div"); | |
| outer.appendChild(clonedSvg); | |
| // Add xmlns so it can be saved properly | |
| clonedSvg.setAttribute("xmlns", "http://www.w3.org/2000/svg"); | |
| // Serialize the SVG | |
| const svgData = new XMLSerializer().serializeToString(clonedSvg); | |
| const svgBlob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" }); | |
| // Create download link | |
| const url = URL.createObjectURL(svgBlob); | |
| const a = document.createElement("a"); | |
| a.href = url; | |
| a.download = "danbooru_tree.svg"; | |
| document.body.appendChild(a); | |
| a.click(); | |
| document.body.removeChild(a); | |
| URL.revokeObjectURL(url); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |