score:1

A possible solution is to create a recursive function which will adjust your `root` data coordinates in your `drawTree` function.

Here is an recursive function which will stagger the nodes left and right. Note the comment where it is mentioned which part of the code controls the calculations of the coordinates.

``````function adjustClashes(data, siblings = 1, index = 1, radius = 20, height = 400) {
//can the node fit in the current x level?
let heightneeded = siblings * radius * 2;
if (heightneeded > height) {
// the code in this if statement will control the calculations for your new coordinates
// In the simplest case we adjust the nodes by staggering odd and even nodes
if (index % 2 != 0){
data.y = data.y + (radius * 2)
} else {
data.y = data.y - (radius * 2)
}
}

// if there are children go deeper and perform same adjustment
if (data.children) {
data.children.forEach((f, i) => {
return adjustClashes( f, data.children.length, i )
})
} else {
return;
}
// finally return the data
return data
}
``````

Full snippet:

``````var data = {
name: "Root",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png",
children: [
{
name: "3",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "4",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "1",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "2",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "1",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "2",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "1",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "2",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "1",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "2",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "1",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "2",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "1",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "2",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "1",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
},
{
name: "2",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
}
],
parent: [
{
name: "1",
img: "https://www.freelogodesign.org/Content/img/logo-samples/flooop.png"
}
]
};

var bgColors = [
"#fd90b5",
"#6ca1e9",
"#fa975c",
"#eb7092",
"#f88962",
"#a094ed",
"#7f8de1"
];
var dr = 0;
// Left data
var data1 = {
name: data.name,
img: data.img,
children: JSON.parse(JSON.stringify(data.children))
};

// Right data
var data2 = {
name: data.name,
img: data.img,
children: JSON.parse(JSON.stringify(data.parent))
};

// Create d3 hierarchies
var right = d3.hierarchy(data1);
var left = d3.hierarchy(data2);

// Render both trees
drawTree(right, "right");
drawTree(left, "left");

// draw single tree
function drawTree(root, pos) {
var refType;
if (pos == "left") refType = "left";
else refType = "right";

var SWITCH_CONST = 1;
if (pos === "left") {
SWITCH_CONST = -1;
}

var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");

var g = svg.append("g").attr("transform", "translate(" + width / 2 + ",0)");

var tree = d3.tree().size([height, (SWITCH_CONST * (width - 150)) / 2]);

tree(root);

data,
siblings = 1,
index = 1,
height = 400
) {
//can the node fit in the current x level?
let heightneeded = siblings * radius * 2;
if (heightneeded > height) {
// the code in this if statement will control the calculations for your new coordinates
// In the simplest case we adjust the nodes by staggering odd and even nodes
if (index % 2 != 0) {
data.y = data.y + radius * 2;
} else {
data.y = data.y - radius * 2;
}
}

// if there are children go deeper and perform same adjustment
if (data.children) {
data.children.forEach((f, i) => {
});
} else {
return;
}
// finally return the data
return data;
}

var nodes = root.descendants();
nodes[0].x = height / 2;

.append("path")
.attr("d", function (d) {
//first return returns a curve and the second will return straight lines in
//return "M" + d.target.y + "," + d.target.x + "C" + (d.target.y + d.source.y) / 2.5 + "," + d.target.x + " " + (d.target.y + d.source.y) / 2 + "," + d.source.x + " " + d.source.y + "," + d.source.x;
return (
"M" +
d.target.y +
"," +
d.target.x +
"A" +
dr +
"," +
dr +
" 1,0 0 " +
d.source.y +
"," +
d.source.x
);
});

.append("text")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("fill", "Black")
.style("font", "normal 12px Arial")
.attr("transform", function (d) {
return (
"translate(" +
(d.source.y + d.target.y) / 2 +
"," +
(d.source.x + d.target.x) / 2 +
")"
);
})
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.data(nodes)
.text(refType);

// Create nodes
var node = g
.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", function (d) {
return "node" + (d.children ? " node--internal" : " node--leaf");
})
.attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")";
});

node
.append("circle")
.attr("class", "icon-wrap")
.attr("x", 0)
.attr("y", 0)
.attr("r", 25)
.style("fill", "black");

node
.append("image")
.attr("href", (d) => d.data.img)
.attr("x", "-25")
.attr("y", "-25")
.attr("height", "50")
.attr("width", "50");

node
.append("text")
.attr("dy", 45)
.style("text-anchor", "middle")
.text((d) => d.data.name);
}``````
``````.node circle {
fill: #999;
}

.node text {
font: 12px sans-serif;
}

.node--internal circle {
fill: #555;
}

fill: none;
stroke: #555;
stroke-opacity: 0.4;
stroke-width: 1.5px;
}``````
``````<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg width="700" height="400"></svg>``````

Update

The following CodePen.io pen shows for example a 3 level staggering of child nodes and even adds a slight margin to space it out more evenly.

To do this simply add `margin` as a default parameter to the `adjustClashes` function and change the if statement as follows:

``````    if (heightneeded > height) {
// the code in this if statement will control the calculations for your new coordinates
// In the simplest case we adjust the nodes by staggering odd and even nodes
if (index % 3 == 0) {
data.y = data.y - radius * 2 - margin ;
} else if (index % 3 == 1) {
data.y = data.y;
} else {
data.y = data.y + radius * 2 + margin;
}
}
``````