function OrgChart(data, {
color = d => 'black',
name = d => d.name,
role = d => d.role,
department = d => d.department,
location = d => d.location,
height = 700,
linkLen = 10,
linkStrngth = 2.2,
repelStrngth = 30
} = {}) {
const root = d3.hierarchy(data);
let transform;
let link;
let node;
const svg = d3.create("svg")
.styles({ "max-width": "100%", "height": "auto" })
.attrs({ "width": width, "height": height, "viewBox": [-width / 2, -height / 2, width, height] })
.on("touchstart", toolTipFns.hide)
const zoom = d3.zoom().scaleExtent([1/2, 8]).on("zoom", (e) => {
link.attr('transform', e.transform)
node.attr('transform', e.transform)
transform = e.transform
toolTipFns.hide()
});
svg.call(zoom)
const simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(d => d.id).distance(linkLen).strength(linkStrngth))
.force("charge", d3.forceManyBody().strength(-repelStrngth))
.force("x", d3.forceX())
.force("y", d3.forceY())
.on("tick", () => {
link.attrs(d => ({ "x1": d.source.x, "y1": d.source.y, "x2": d.target.x, "y2": d.target.y }));
node.attrs(d => ({ "cx": d.x, "cy": d.y }));
});
function update() {
const link_data = root.links();
const node_data = root.descendants();
link = svg.selectAll('.link').data(link_data, d => d.target.id)
link.exit().remove()
const linkEnter = link
.enter()
.append('line')
.attr('class', 'link')
.styles({ "stroke": "#999", "opacity": 0.6 })
.lower()
link = linkEnter.merge(link)
node = svg.selectAll('.node').data(node_data, d => d.id)
node.exit().remove()
const nodeEnter = node
.enter()
.append('circle')
.attrs(d => ({
'class': 'node',
'stroke': (d.children || d._children) ? '#000' : '#fff',
'stroke-width': 1.5,
'stroke-dasharray': d._children ? '2' : '',
'r': d._children ? 7 : 5
}))
.styles(d => ({ 'fill': color(d.data), 'opacity': 1 }))
.raise()
.on('mouseover', toolTipFns.show(name, role, department, location))
.on('mousemove', toolTipFns.move)
.on('mouseout', toolTipFns.hide)
.on('click', (e, d) => { clickFn(d); update(); })
.call(dragFn(simulation))
node = nodeEnter.merge(node)
if (transform) {
link.attr('transform', transform)
node.attr('transform', transform)
}
simulation.nodes(node_data)
simulation.force('link').links(link_data)
}
update()
return svg.node();
}