-
-
Save sanjeevkse/6965c8735c0d801c63e271cc4f23acde to your computer and use it in GitHub Desktop.
v
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
#artboard { | |
width: 800px; /* Initial width */ | |
height: 600px; /* Initial height */ | |
overflow: hidden; | |
border: 1px solid #000; | |
position: relative; | |
} | |
#draggable-container { | |
width: 2000px; /* Set a large width to make it effectively infinite */ | |
height: 2000px; /* Set a large height to make it effectively infinite */ | |
cursor: grab; | |
transform-origin: top left; | |
transition: transform 0.2s ease-in-out; | |
/* Add an initial transform scale */ | |
transform: scale(1); | |
} | |
#treeSVG { | |
position: absolute; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="artboard"> | |
<div id="draggable-container"> | |
<svg id="treeSVG" width="2000" height="2000"></svg> | |
</div> | |
</div> | |
<div id="nodeInfo"></div> | |
<button id="zoom-in">Zoom In</button> | |
<button id="zoom-out">Zoom Out</button> | |
<script> | |
const artboard = document.getElementById("artboard"); | |
const draggableContainer = document.getElementById("draggable-container"); | |
const svg = document.getElementById("treeSVG"); | |
// Define your tree hierarchy data here | |
const treeData = { | |
name: "Root", | |
level: 0, | |
children: [ | |
{ | |
name: "Node 1", | |
level: 1, | |
children: [ | |
{ | |
name: "Node 1.1", | |
children: [ | |
{ name: "Node 1.1.1" }, | |
{ name: "Node 1.1.2" }, | |
{ name: "Node 1.1.3" }, | |
{ name: "Node 1.1.4" }, | |
], | |
}, | |
{ name: "Node 1.2" }, | |
], | |
}, | |
{ name: "Node 2" }, | |
{ | |
name: "Node 3", | |
children: [{ name: "Node 3.1" }, { name: "Node 3.2" }], | |
}, | |
], | |
}; | |
function drawTree(node, x, y, level) { | |
const spacingX = 100; | |
const spacingY = 100; | |
const textPadding = 10; | |
// Measure text size for dynamic rectangle width | |
const textElement = document.createElementNS( | |
"http://www.w3.org/2000/svg", | |
"text" | |
); | |
textElement.textContent = node.name; | |
svg.appendChild(textElement); | |
const textWidth = textElement.getBBox().width; | |
svg.removeChild(textElement); | |
// Calculate rectangle width based on text size | |
const rectWidth = textWidth + textPadding * 2; | |
const rectHeight = 40; | |
const borderRadius = 10; | |
// Draw the rectangle | |
const rect = document.createElementNS( | |
"http://www.w3.org/2000/svg", | |
"rect" | |
); | |
rect.setAttribute("x", x - rectWidth / 2); | |
rect.setAttribute("y", y - rectHeight / 2); | |
rect.setAttribute("width", rectWidth); | |
rect.setAttribute("height", rectHeight); | |
rect.setAttribute("rx", borderRadius); | |
rect.setAttribute("fill", "#0050FE"); | |
svg.appendChild(rect); | |
// Add text to the rectangle | |
const text = document.createElementNS( | |
"http://www.w3.org/2000/svg", | |
"text" | |
); | |
text.setAttribute("x", x); | |
text.setAttribute("y", y); | |
text.setAttribute("text-anchor", "middle"); | |
text.setAttribute("alignment-baseline", "middle"); | |
text.setAttribute("fill", "white"); | |
text.textContent = node.name; | |
svg.appendChild(text); | |
// Draw connections to children with Bezier curves | |
if (node.children) { | |
const childY = y + spacingY; | |
node.children.forEach((child, index) => { | |
const childX = | |
x - | |
(spacingX * (node.children.length - 1)) / 2 + | |
index * spacingX; | |
// Draw Bezier curve | |
const curve = document.createElementNS( | |
"http://www.w3.org/2000/svg", | |
"path" | |
); | |
const curveD = `M${x} ${y + rectHeight / 2} C${x} ${ | |
y + rectHeight / 2 + spacingY / 2 | |
}, ${childX} ${childY - spacingY / 2}, ${childX} ${ | |
childY - rectHeight / 2 | |
}`; | |
curve.setAttribute("d", curveD); | |
curve.setAttribute("fill", "transparent"); | |
curve.setAttribute("stroke", "#BCC4CC"); | |
curve.setAttribute("stroke-width", "2"); | |
svg.appendChild(curve); | |
// Recursively draw child nodes | |
drawTree(child, childX, childY, level + 1); | |
}); | |
} | |
// Add click event listener to the rectangle | |
rect.addEventListener("click", () => { | |
updateNodeInfo(node); | |
}); | |
} | |
function updateNodeInfo(selectedNode) { | |
const nodeInfo = document.getElementById("nodeInfo"); | |
nodeInfo.textContent = `Selected Node: ${JSON.stringify(selectedNode)}`; | |
} | |
// Start drawing from the root node | |
drawTree(treeData, svg.clientWidth / 2, 50, 0); | |
// Implement drag and pan functionality | |
let isDragging = false; | |
let startX, startY, scrollLeft, scrollTop; | |
draggableContainer.addEventListener("mousedown", (e) => { | |
isDragging = true; | |
startX = e.clientX; | |
startY = e.clientY; | |
scrollLeft = artboard.scrollLeft; | |
scrollTop = artboard.scrollTop; | |
draggableContainer.style.cursor = "grabbing"; | |
}); | |
window.addEventListener("mousemove", (e) => { | |
if (isDragging) { | |
const deltaX = e.clientX - startX; | |
const deltaY = e.clientY - startY; | |
artboard.scrollLeft = scrollLeft - deltaX; | |
artboard.scrollTop = scrollTop - deltaY; | |
} | |
}); | |
window.addEventListener("mouseup", () => { | |
isDragging = false; | |
draggableContainer.style.cursor = "grab"; | |
}); | |
// Zoom-in and zoom-out buttons | |
document.getElementById("zoom-in").addEventListener("click", () => { | |
const currentScale = getComputedStyle(draggableContainer).transform; | |
const scaleValue = currentScale.match(/matrix\(([^,]+),/)[1]; | |
const newScale = parseFloat(scaleValue) * 1.2; // Adjust the zoom factor as needed | |
draggableContainer.style.transform = `scale(${newScale})`; | |
}); | |
document.getElementById("zoom-out").addEventListener("click", () => { | |
const currentScale = getComputedStyle(draggableContainer).transform; | |
const scaleValue = currentScale.match(/matrix\(([^,]+),/)[1]; | |
const newScale = parseFloat(scaleValue) / 1.2; // Adjust the zoom factor as needed | |
draggableContainer.style.transform = `scale(${newScale})`; | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment