chart = {
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.style("background", "aliceblue");
const redCircleTop = { x: 0, y: 80 };
const redCircleBottom = { x: 0, y: height - 80 };
const redCircleRight = { x: Math.min(200, width * 0.4), y: height / 2 };
const redCircleCenter = findCenter(
redCircleTop,
redCircleBottom,
redCircleRight
);
const [radius, larc_flag, sweep_flag] = arcWithPoints(
[redCircleTop.x, redCircleTop.y],
[redCircleBottom.x, redCircleBottom.y],
[redCircleRight.x, redCircleRight.y]
);
const pathDefinition = `M${redCircleTop.x},${redCircleTop.y} A${radius},${radius},0,${larc_flag},${sweep_flag},${redCircleBottom.x},${redCircleBottom.y}`;
const bigCircle = svg
.append("path")
.attr("fill", "red")
.attr("d", pathDefinition);
const path = bigCircle.node();
const circlePadding = 60;
const spaceBetweenChildren = 50;
const totalLength = path.getTotalLength();
const halfLength = totalLength / 2;
const maxAvailableSpace = totalLength - circlePadding * 2;
const maxVisibleChildrenCount =
Math.floor(maxAvailableSpace / spaceBetweenChildren) + 1;
const visibleChildrenCount = Math.min(maxVisibleChildrenCount, childrenCount);
const requiredSpace = (visibleChildrenCount - 1) * spaceBetweenChildren;
const distanceWhereFirstPointShouldStart = halfLength - requiredSpace / 2;
const children = [...Array(visibleChildrenCount).keys()].map((key, index) => {
const distanceFromTop =
index * spaceBetweenChildren + distanceWhereFirstPointShouldStart;
const pointOnPath = path.getPointAtLength(distanceFromTop);
const position = appendDistance(redCircleCenter, pointOnPath, 30);
return position;
});
children.forEach(child => {
svg
.append("circle")
.attr("cx", child.x)
.attr("cy", child.y)
.attr("fill", "blue")
.attr("r", 10);
});
return svg.node();
}