chart = {
const links = data.links.map(d => Object.create(d));
const nodes = data.nodes.map(d => Object.create(d));
const zoom = d3
.zoom()
.scaleExtent([0.5, 3])
.on("zoom", _ => g.attr("transform", d3.event.transform))
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).distance(nodeDistance).id(d => d.id))
.force("charge", d3.forceManyBody().strength(chargeStr))
.force("collide", d3.forceCollide(d => getRadius(d.group)))
.force("center", d3.forceCenter(width / 2, height / 2))
.force("x", d3.forceX(width/ xDenom).strength(xStr))
.force("y", d3.forceY(height * yDenom).strength(yStr))
const svg = d3.select(DOM.svg(width, height));
svg.call(zoom);
const defs = svg.append('defs');
defs
.selectAll('clipPath')
.data(groupData)
.join('clipPath')
.attr('id', d => d.name + '-clip')
.append('circle')
.attr('r', d => nodeRadius * d.mx);
const g = svg.append("g")
const linkG = g
.append('g')
.selectAll('g')
.data(links)
.join('g');
const line = linkG
.append('path')
.attr('id', d => d.index)
.attr('stroke-opacity', 0.6)
.attr('stroke', '#ccc')
.attr('stroke-width', '1');
const lineText = linkG
.append('text')
.append('textPath')
.attr('href', d => `#${d.index}`)
.attr('startOffset', '50%')
.append('tspan')
.attr('class', 'link-arrow')
.attr("style", "text-anchor: middle; font: 14px sans-serif; user-select: none")
.attr('fill', '#bbb')
// .text(d => d.source.id == "Warren Buffet" | d.source.id == "Organizations" ? '' : '→')
.text(d => (d.target.id == "Warren Buffet" & (d.source.id =="Locations" | d.source.id =="Organizations"|d.source.id =="Miscellaneous")) ? 'Groups' : '')
// .text(d => (d.target.id != "Warren Buffet" & (d.source.id !="Organizations" | d.source.id !="Locat
// .text(d => d.source.id == "Organizations" ? '' : 'Related Orgs')
.attr('dy', 1.75);
const node = g.append("g")
.selectAll("g")
.data(nodes)
.join("g")
.attr("data-name", d => d.id)
.attr("class", d => `img-group ${d.group}`)
.attr("fill", "none")
.attr("stroke",hlColor)
.call(drag(simulation));
// function trumpCheck(id) {
// return id == "Motilal Oswal" ? (nodeRadius * 20) : nodeRadius
// }
const cir = node
.append('circle')
.attr('r', d => getRadius(d.group))
.attr('stroke', '#D7BB6E')
.attr('stroke-width', 1)
// .attr('fill', '#999')
.attr("fill", function(d) {
if (d.group== "person" & d.id!="Warren Buffet") {
return "#39D98A";
}
if (d.group== "org" & d.id!="Organizations") {
return "#005290";
}
if (d.group== "location" & d.id!="Locations") {
return "yellow";
}
if (d.group== "misc" & d.id!="Miscellaneous") {
return "#0091FF";
}
if (d.id== "Warren Buffet") {
return "#FA641B";
}
if (d.id== "Organizations"|d.id== "Locations"|d.id== "Miscellaneous") {
return "red";
}
return "#999";
});
const img = node
.append('image')
// .attr('xlink:href', "https://media.miamiherald.com/static/media/projects/2019/yang-interactive/GenderlessIcon.74c2fa61.jpg")
.attr('clip-path', d => `url(#${d.group}-clip)`)
// .attr('width', d => getRadius(d.group) * 2)
// .attr('height', d => getRadius(d.group) * 2)
.attr('width', d => getRadius(d.group) )
.attr('height', d => getRadius(d.group) )
.attr('x', d => getRadius(d.group) * -1)
.attr('y', d => getRadius(d.group) * -1);
tooltip.attr("class", "tooltip")
.style("position", "absolute")
.style("visibility", "hidden");
node.on('touchmove mousemove', d => {
tooltip.style("visibility", "visible");
tooltip.text(d.tooltip);
tooltip.style("top", `${d3.event.pageY-10}px`).style("left",`${d3.event.pageX+10}px`);
});
linkG.on('touchmove mousemove', function(d) {
tooltip.style('visibility', 'visible');
tooltip.text(`${d.source.id} ${d.relationship} ${d.target.id}`);
tooltip
.style('top', `${d3.event.pageY - 10}px`)
.style('left', `${d3.event.pageX + 10}px`);
d3.select(this)
.select('path')
.style('stroke', hlColor)
.style('stroke-opacity', 1)
.style('stroke-width', '2');
d3.selectAll(
`g[data-name="${d.source.id}"] > circle, g[data-name="${
d.target.id
}"] > circle`
)
.style('stroke', hlColor)
.style('stroke-width', '6');
});
node.on('touchend mouseleave', () => tooltip.style('visibility', 'hidden'));
linkG.on('touchend mouseleave', function(d) {
tooltip.style('visibility', 'hidden');
d3
.select(this)
.select('path')
.node().style = '';
d3.selectAll(
`g[data-name="${d.source.id}"] > circle, g[data-name="${
d.target.id
}"] > circle`
)
.style('stroke', '#333')
.style('stroke-width', '2');
});
let pres = node.filter(d => d.group == "person").datum();
let tVict = node.filter(d => d.id == 'Warren Buffet').datum();
// let tOrg = node.filter(d => d.id == 'RBI').datum();
simulation.on("tick", function() {
pres.fy = height / 2;
pres.fx = width / 2;
tVict.fy = height / 2 ;
tVict.fx = width / 2 ;
// tOrg.fy = height / 6;
// tOrg.fx = width / 2 - nodeRadius * 2;
line.attr("d", d => `M ${d.source.x} ${d.source.y} L ${d.target.x} ${d.target.y}`)
node.attr('transform', d => `translate(${d.x},${d.y})`);
});
invalidation.then(() => simulation.stop());
return svg.node();
}