chart = {
const svg = d3.select(DOM.svg(width, height))
.style("width", "100%")
.style("height", "auto")
.style("padding", "8px")
.style("box-sizing", "border-box")
.style("font", "10px sans-serif")
const {nodes, links} = sankey(data);
const g = svg.append("g");
const link = g.append("g")
.attr("fill", "none")
.attr("stroke-opacity", 0.5)
.selectAll("g")
.data(links)
.join("g")
var node = g.append("g").selectAll(".node")
.data(nodes)
.join("g")
.attr("class", d => d.type == "person" ? "node circle": "node rect")
g.selectAll(".node.rect").append("rect")
.attr("x", d => d.x0)
.attr("y", d => (d.y1 + d.y0) / 2 - 15)
.attr("height", d => 30)
.attr("width", d => d.x0 > width/2 ? 0 : 30)
.attr("fill", "#be005b")
//.attr("fill", d => d.type == "person" ? color(d.name) : d.colour)
var fo = node.append("foreignObject")
.attr("x",function(d){
if(d.depth == 1){
return d.x0 - 150
}})
.attr("y", d => ((d.y1 + d.y0) / 2) -100)
.attr("height", 250)
.attr("width", function (d) {
if (d.type == "article" && d.x0 < width/2){
return 359
}
else{
return 0
}})
var div = fo.append("xhtml:div")
.style('position', 'absolute')
.style('width', '300px')
.style('height', '225px')
.style('padding', '10px')
.style('background', 'rgba(255,255,255)')
.style('border-radius', '4px')
.style('color', 'black')
.style("box-shadow", "5px 5px 10px grey")
.html(function (d) {
return "<h2 style=margin:0>Title</h2><hr style=padding:0.5rem;margin:0><p>"+d.name+"</p><h3 style=color:#be005b;padding-top:5%>DOI</h3>"+ d.DOI+"<hr style=padding:0.5rem;margin:0><h3 style=color:#be005b;padding-top:5%>Authors</h3>" + d.authors + "<hr style=padding:0.5rem;margin:0><h3 style=color:#be005b;padding-top:5%>Year</h3>" + d.year
})
.on("mouseover", function(d) {
var index = d.index
d.sourceLinks.forEach(function(d) {
var id = d.target.id
filterOver3(id,index)
})
d3.select(this).style("cursor", "pointer")
})
.on('mouseout', function (d,nodes) {
filterOut()
});;
g.selectAll(".node.circle").append("circle")
.attr("cx", d => (d.x1 + d.x0)/2 + 72.5)
.attr("cy", d => (d.y1 + d.y0)/2)
.attr("r", d => 50)
.attr("fill", d => d.colour)
.style("fill", d =>`url(#pattern${d.id})`)
.on("mouseover", function(d) {
d3.select(this).attr("r",60)
d3.selectAll("#text" + d.id).attr("font-weight", 600).attr("font-size", 35)
var id = d.id
var image = "<img src= https://static.observableusercontent.com/files/5546d2446f6cb2f1c0bedddb1c5f5412f1aa0f48cfbcab99dcc7db4b733c6d63ea15462328579a5224bad0952482823c07e5fa907f763eecd012329b686c9b5c />"
d.targetLinks.forEach(function(d) {
var index = d.source.index
filterOver2(index,id)
})
d3.select(this).style("cursor", "pointer")
tooltip
.html("<p style=padding:0;margin:0>"+d.name+"</p>" + "<hr>"+ image +"<h3 style=color:#be005b;padding-top:5%;white-space:nowrap >Profile</h3><p>"+ d.profile)
.style('visibility', 'visible')
})
.on('mousemove', function (d) {
tooltip
.style('top', d3.event.clientY + 10 + 'px')
.style('left', d3.event.clientX + 30 + 'px')
.style("display", "inline-block");
})
.on('mouseout', function (d,nodes) {
filterOut()
d3.selectAll("#text" + d.id).attr("font-weight", 600).attr("font-size", 30)
d3.select(this).attr("r",50)
tooltip.html(``).style('visibility', 'hidden');
});
const gradient = link.append("linearGradient")
.attr("id", d => (d.uid = DOM.uid("link")).id)
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", d => d.source.x1)
.attr("x2", d => d.target.x0);
gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", d => d.source.colour);
gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", d => d.target.colour);
/* gradient.append("animate")
.attr("attributeName","x1")
.attr("values","0%; 50%") //let x1 run to 200% instead of 100%
.attr("dur","3s")
.attr("repeatCount","indefinite");
gradient.append("animate")
.attr("attributeName","x2")
.attr("values","50%; 100%") //let x2 run to 300% instead of 200%
.attr("dur","3s")
.attr("repeatCount","indefinite");*/
var linking = d3.linkHorizontal()
.x(function(d) {
return d.x1
})
.y(function(d) {
return ((d.y1 + d.y0) / 2);
})
link.append("path")
.attr("d", d => linking(d))
.attr("id", d => d.target.depth == 2 ? "path" + d.target.id : "path" + d.target.index)
.attr("class", d => d.target.depth == 1? "path" + d.target.index : "path" + d.source.index)
.attr("opacity", 0)
/* .attr("stroke", d => edgeColor === "none" ? "#aaa"
: edgeColor === "path" ? d.uid
: edgeColor === "input" ? color(d.source.name)
: color(d.target.name)) */
//.attr("stroke", d => d.target.colour)
.attr("stroke", d => d.uid )
//.attr("stroke-width", d => Math.max(1, d.width));
.attr("stroke-width", 10);
g.append("g")
.style("font", "10px sans-serif")
.selectAll("text")
.data(nodes)
.join("text")
// .attr("x", d => d.x0 < width / 2 ? d.x1 + 6 : d.x0 + 150)
.attr("x",function(d){
if(d.x0 < width / 2){
if(d.depth == 0){
return d.x0 - 10
}
else { return d.x0}
}
else{
return d.x0 + 160
}
})
.attr("y", d => d.depth == 1 ? ((d.y1 + d.y0) / 2) - 50: (d.y1 + d.y0) / 2)
.attr("dy", "0.35em")
.attr("id", d => "text" + d.id)
.attr("font-weight", d => d.depth == 1 ? 100: 600)
.attr("font-size", d => d.depth == 1 ? 0: 30)
.attr("text-anchor", d => d.x0 < width / 2 ? "End" : "Start")
.attr("text-anchor",function(d){
if(d.x0 < width / 2){
if(d.depth == 1){
return "Middle"
}
else { return "End"}
}
else{
return "Start"
}
})
.text(d => d.sourceLinks.length == 0 && d.targetLinks.length == 0 ? null : d.name)
/* .on("mouseover", function(d) {
d3.select(this).style("cursor", "pointer")
tooltip
.html("Name: " + d.name)
.style('visibility', 'visible')})
.on('mousemove', function (d) {
tooltip
.style('top', d3.event.clientY + 10 + 'px')
.style('left', d3.event.clientX + 20 + 'px')
.style("display", "inline-block");
})
.on('mouseout', function (d, nodes) {
tooltip.html(``).style('visibility', 'hidden');
});*/
var uniform =
d3.range(0, 7).map((_,i) => ({
id: i,
size: Math.ceil(d3.randomUniform(1, 5)(_)),
url: image_urls[i]
}));
let pack = data => d3.pack()
.size([width, width])
.padding(0)
(d3.hierarchy({children: data})
.sum(d => d.size))
const root = pack(uniform);
const defs = svg.append("defs")
.selectAll("pattern")
.data(root.leaves())
.enter();
defs.append("pattern")
.attr("id", d => "pattern" + d.data.id)
.attr("width", 1)
.attr("height", 1)
.append('image')
.attr("xlink:href", d => d.data.url)
document.body.appendChild(svg.node());
const box = g.node().getBBox();
svg.remove()
.attr("width", box.width)
.attr("height", box.height)
.attr("viewBox", `${box.x} ${box.y} ${box.width + 100} ${box.height}`);
svg.call(d3.zoom()
.extent([[0, 0], [width, height]])
.scaleExtent([0.75, 8])
.on("zoom", zoomed));
function zoomed() {
g.attr("transform", d3.event.transform);
}
d3.select('#NoOneButton').on('click', () => {
d3.selectAll('path')
.attr("opacity", 0)
d3.selectAll("text").attr("pointer-events", "default");
d3.selectAll("rect").attr("pointer-events", "default");
d3.selectAll("circle").attr("pointer-events", "default")//.attr("cx", d => (d.x1 + d.x0)/2 + 72.5);;
});
d3.select('#AllButton').on('click', () => {
d3.selectAll('path')
.attr("opacity", 0.8)
d3.selectAll("text").attr("pointer-events", "none");
d3.selectAll("rect").attr("pointer-events", "none");
d3.selectAll("circle").attr("pointer-events", "none")//.attr("cx", d => (d.x1 + d.x0)/2 + 62.5);
});
return svg.node();
}