Open dlrandy opened 1 year ago
<!DOCTYPE html>
<html>
<head>
<title>Org Chart with D3.js Hierarchy</title>
<style>
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
.sibling-link {
stroke: #999;
stroke-width: 1px;
stroke-dasharray: 5, 5;
marker-end: url(#arrow); /* Add arrow marker */
}
</style>
</head>
<body>
<svg width="960" height="500">
<defs>
<marker
id="arrow"
markerWidth="10"
markerHeight="10"
refX="10"
refY="3"
orient="auto"
markerUnits="strokeWidth"
>
<path d="M0,0 L0,6 L9,3 z" fill="#999" />
</marker>
</defs>
</svg>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script>
const data = {
name: "CEO",
children: [
{
name: "CFO",
children: [
{
name: "Accounting Manager",
linkCondition: true
},
{
name: "Finance Manager",
linkCondition: false
}
]
},
{
name: "CTO",
children: [
{
name: "Engineering Manager",
linkCondition: true
},
{
name: "Software Architect",
linkCondition: true
},
{
name: "Frontend Developer",
linkCondition: false
},
{
name: "Backend Developer",
linkCondition: true
}
]
},
{
name: "COO",
children: [
{
name: "Operations Manager",
linkCondition: true
},
{
name: "HR Manager",
linkCondition: true
},
{
name: "Sales Manager",
linkCondition: true
}
]
}
]
};
const svg = d3.select("svg");
const width = +svg.attr("width");
const height = +svg.attr("height");
const g = svg.append("g").attr("transform", "translate(40,0)");
const tree = d3.tree().size([height, width - 160]);
const root = d3.hierarchy(data);
tree(root);
const link = g
.selectAll(".link")
.data(root.links())
.enter()
.append("path")
.attr("class", "link")
.attr(
"d",
d3
.linkHorizontal()
.x((d) => d.y)
.y((d) => d.x)
);
// Add conditional sibling links
root.each((node) => {
if (node.parent) {
const siblings = node.parent.children;
const currentNodeIndex = siblings.findIndex((d) => d === node);
for (let i = currentNodeIndex + 1; i < siblings.length; i++) {
const currentSibling = siblings[i];
if (shouldLinkSiblings(node.data, currentSibling.data)) {
g.append("path")
.attr("class", "sibling-link")
.attr("d", () => {
return `M${node.y},${node.x}L${currentSibling.y},${currentSibling.x}`;
});
}
}
}
});
function shouldLinkSiblings(nodeData, siblingData) {
return nodeData.linkCondition && siblingData.linkCondition;
}
const node = g
.selectAll(".node")
.data(root.descendants())
.enter()
.append("g")
.attr("class", "node")
.attr("transform", (d) => `translate(${d.y},${d.x})`);
node.append("circle").attr("r", 5);
node
.append("text")
.attr("dy", "0.31em")
.attr("x", (d) => (d.children ? -6 : 6))
.attr("text-anchor", (d) => (d.children ? "end" : "start"))
.text((d) => d.data.name);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Org Chart with D3.js Hierarchy</title>
<style>
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
.sibling-link {
stroke: #999;
stroke-width: 1px;
stroke-dasharray: 5, 5;
}
</style>
</head>
<body>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script>
const data = {
"name": "CEO",
"children": [
{
"name": "CFO",
"children": [
{
"name": "Accounting Manager",
"linkCondition": true
},
{
"name": "Finance Manager",
"linkCondition": false
}
]
},
{
"name": "CTO",
"children": [
{
"name": "Engineering Manager",
"linkCondition": true
},
{
"name": "Software Architect",
"linkCondition": true
},
{
"name": "Frontend Developer",
"linkCondition": false
},
{
"name": "Backend Developer",
"linkCondition": true
}
]
},
{
"name": "COO",
"children": [
{
"name": "Operations Manager",
"linkCondition": true
},
{
"name": "HR Manager",
"linkCondition": true
},
{
"name": "Sales Manager",
"linkCondition": true
}
]
}
]
};
const svg = d3.select("svg");
const width = +svg.attr("width");
const height = +svg.attr("height");
const g = svg.append("g").attr("transform", "translate(40,0)");
const tree = d3.tree().size([height, width - 160]);
const root = d3.hierarchy(data);
tree(root);
const link = g
.selectAll(".link")
.data(root.links())
.enter()
.append("path")
.attr("class", "link")
.attr("d", d3.linkHorizontal().x(d => d.y).y(d => d.x));
// Add conditional sibling links
root.each(node => {
if (node.parent) {
const siblings = node.parent.children;
const currentNodeIndex = siblings.findIndex(d => d === node);
for (let i = currentNodeIndex + 1; i < siblings.length; i++) {
const currentSibling = siblings[i];
if (
shouldLinkSiblings(node.data, currentSibling.data)
) {
g.append("path")
.attr("class", "sibling-link")
.attr("d", () => {
return `M${node.y},${node.x}L${currentSibling.y},${currentSibling.x}`;
});
}
}
}
});
function shouldLinkSiblings(nodeData, siblingData) {
return (
nodeData.linkCondition &&
siblingData.linkCondition
);
}
const node = g
.selectAll(".node")
.data(root.descendants())
.enter()
.append("g")
.attr("class", "node")
.attr("transform", d => `translate(${d.y},${d.x})`);
node.append("circle").attr("r", 5);
node
.append("text")
.attr("dy", "0.31em")
.attr("x", d => (d.children ? -6 : 6))
.attr("text-anchor", d => (d.children ? "end" : "start"))
.text(d => d.data.name);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Org Chart with D3.js Hierarchy</title>
<style>
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
.sibling-link {
stroke: #999;
stroke-width: 1px;
stroke-dasharray: 5,5;
}
</style>
</head>
<body>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script>
const data = {
"name": "CEO",
"children": [
{
"name": "CFO",
"children": [
{ "name": "Accounting Manager" },
{ "name": "Finance Manager" }
]
},
{
"name": "CTO",
"children": [
{ "name": "Engineering Manager" },
{ "name": "Software Architect" },
{ "name": "Frontend Developer" },
{ "name": "Backend Developer" }
]
},
{
"name": "COO",
"children": [
{ "name": "Operations Manager" },
{ "name": "HR Manager" },
{ "name": "Sales Manager" }
]
}
]
};
const svg = d3.select("svg");
const width = +svg.attr("width");
const height = +svg.attr("height");
const g = svg.append("g").attr("transform", "translate(40,0)");
const tree = d3.tree().size([height, width - 160]);
const root = d3.hierarchy(data);
tree(root);
const link = g.selectAll(".link")
.data(root.links())
.enter().append("path")
.attr("class", "link")
.attr("d", d3.linkHorizontal()
.x(d => d.y)
.y(d => d.x));
// Add conditional sibling links
root.each(node => {
if (node.parent) {
const siblings = node.parent.children;
for (let i = 1; i < siblings.length; i++) {
const currentSibling = siblings[i];
const previousSibling = siblings[i - 1];
if (shouldLinkSiblings(previousSibling, currentSibling)) {
g.append("path")
.attr("class", "sibling-link")
.attr("d", () => {
return `M${previousSibling.y},${previousSibling.x}L${currentSibling.y},${currentSibling.x}`;
});
}
}
}
});
function shouldLinkSiblings(previousSibling, currentSibling) {
// Define your condition here
// Return true to link the siblings, false to exclude the link
// Example condition: Only link siblings if their names start with the same letter
return previousSibling.data.name.charAt(0) === currentSibling.data.name.charAt(0);
}
const node = g.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("class", "node")
.attr("transform", d => `translate(${d.y},${d.x})`);
node.append("circle")
.attr("r", 5);
node.append("text")
.attr("dy", "0.31em")
.attr("x", d => d.children ? -6 : 6)
.attr("text-anchor", d => d.children ? "end" : "start")
.text(d => d.data.name);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Org Chart with D3.js Hierarchy</title>
<style>
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script>
const data = {
"name": "CEO",
"children": [
{
"name": "CFO",
"children": [
{ "name": "Accounting Manager" },
{ "name": "Finance Manager" }
]
},
{
"name": "CTO",
"children": [
{ "name": "Engineering Manager" },
{ "name": "Software Architect" },
{ "name": "Frontend Developer" },
{ "name": "Backend Developer" }
]
},
{
"name": "COO",
"children": [
{ "name": "Operations Manager" },
{ "name": "HR Manager" },
{ "name": "Sales Manager" }
]
}
]
};
const svg = d3.select("svg");
const width = +svg.attr("width");
const height = +svg.attr("height");
const g = svg.append("g").attr("transform", "translate(40,0)");
const tree = d3.tree().size([height, width - 160]);
const root = d3.hierarchy(data);
tree(root);
const link = g.selectAll(".link")
.data(root.links())
.enter().append("path")
.attr("class", "link")
.attr("d", d3.linkHorizontal()
.x(d => d.y)
.y(d => d.x));
// Add sibling links
root.each(node => {
if (node.children) {
const siblings = node.children;
for (let i = 1; i < siblings.length; i++) {
const sibling = siblings[i];
const previousSibling = siblings[i - 1];
g.append("path")
.attr("class", "link sibling-link")
.attr("d", () => {
return `M${previousSibling.y},${previousSibling.x}L${sibling.y},${sibling.x}`;
});
}
}
});
const node = g.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("class", "node")
.attr("transform", d => `translate(${d.y},${d.x})`);
node.append("circle")
.attr("r", 5);
node.append("text")
.attr("dy", "0.31em")
.attr("x", d => d.children ? -6 : 6)
.attr("text-anchor", d => d.children ? "end" : "start")
.text(d => d.data.name);
</script>
</body>
</html>