-
-
Save sanjeevkse/917abba04b596bef6a8ec877c6055b3c to your computer and use it in GitHub Desktop.
v
This file contains hidden or 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", | |
level: 2, | |
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", level: 2 }, | |
], | |
}, | |
{ | |
name: "Node 2", | |
level: 1, | |
children: [ | |
{ name: "Node 2.1" }, | |
{ name: "Node 2.2" }, | |
{ name: "Node 2.3" }, | |
{ name: "Node 2.4" }, | |
], | |
}, | |
{ | |
name: "Node 3", | |
level: 1, | |
children: [{ name: "Node 3.1" }, { name: "Node 3.2" }], | |
}, | |
], | |
}; | |
function drawTree(node, x, y, level) { | |
const spacingX = 160; | |
const spacingY = 80; | |
const textPadding = 10; | |
// Create a group (g) element to contain both the rectangle and text | |
const group = document.createElementNS( | |
"http://www.w3.org/2000/svg", | |
"g" | |
); | |
// Calculate rectangle dimensions | |
const rectWidth = 80; | |
const textElement = document.createElementNS( | |
"http://www.w3.org/2000/svg", | |
"text" | |
); | |
textElement.textContent = node.name; | |
svg.appendChild(textElement); | |
const textHeight = textElement.getBBox().height; | |
svg.removeChild(textElement); | |
const rectHeight = textHeight + textPadding * 2; | |
const borderRadius = 10; | |
// Draw the rectangle and add it to the group | |
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"); | |
group.appendChild(rect); | |
// Add text to the group | |
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; | |
group.appendChild(text); | |
// Add the group to the SVG | |
svg.appendChild(group); | |
// Draw connections to children with Bezier curves | |
if (node.children) { | |
const childX = x + spacingX; | |
node.children.forEach((child) => { | |
const childY = | |
y - | |
(spacingY * (node.children.length - 1)) / 2 + | |
spacingY * node.children.indexOf(child); | |
// Draw Bezier curve | |
const curve = document.createElementNS( | |
"http://www.w3.org/2000/svg", | |
"path" | |
); | |
const curveD = `M${x + rectWidth / 2} ${y} C${ | |
x + rectWidth / 2 + spacingX / 2 | |
} ${y}, ${childX - spacingX / 2} ${childY}, ${ | |
childX - rectWidth / 2 | |
} ${childY}`; | |
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 group (for both text and rectangle) | |
group.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, 300, 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