chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, totalWidth, totalHeight])
.style('background','white');
const simulation = d3.forceSimulation(nodes_JSON)
.force("x", d3.forceX(function(d) {
return xScale(d.Year);
}).strength(1))
.force("y", d3.forceY(function(d) {
return yScale(d.Xposition);
}))
.force("collide", d3.forceCollide(function(d){
return radius(d.citations+1)
}))
.stop();
simulation.tick(120);
const circles = svg.append('g').selectAll(null)
.data(nodes_JSON)
.enter()
.append("circle")
.attr("id", function(d){
return "p_"+d.ID
})
.attr("year", function(d){
return d.Year
})
.attr("r", function(d){
return radius(d.citations)
})
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
// style them
.attr("fill", function(d) { if (d.citations > 0){ return "RebeccaPurple" } else {return "LightGrey"} })
.style("stroke", function(d) { if (d.citations > 0){ return "none" } else {return "RebeccaPurple"} })
.style("opacity","0.8")
// add mouse over event listeners
.on("mouseover", function(d) {
onMouseOver(d)
})
.on("mouseout", function(d) {
onMouseOut(d)
});
function onMouseOver(d){
let circle = document.getElementById("p_"+d.ID)
circle.style.stroke = "none";
circle.setAttribute("fill", "MidnightBlue");
tooltip.transition()
.duration(200)
.style("opacity", 1)
tooltip.html("<b>"+ d.title + "</b><br/>" + d.creator + ", "+ d.Year +"<br/><br/>" + d.citations + " citations");
//showLinks(d);
}
function onMouseOut(d){
let circle = document.getElementById("p_"+d.ID)
if (d.citations > 0) {
circle.setAttribute("fill", "RebeccaPurple");
}
else {
circle.style.stroke = "RebeccaPurple";
circle.setAttribute("fill", "LightGrey");
}
tooltip.transition()
.duration(500)
.style("opacity", 0);
//hideLinks(d);
}
///////////////////////////
// LEGEND
const legend = svg.append("foreignObject")
.attr("width",width)
.attr("height",height)
.style("pointer-events","none")
.append("xhtml:div")
.attr("class", "legend")
.style("opacity", 1)
.style("position", "absolute")
.style("width", "360px")
.style("top", (margins + 70)+"px")
.style("left", (margins)+"px")
.style("padding", "10px")
.style("font", "10px sans-serif")
.style("color","grey")
.style("line-height", "175%")
.style("background", "none")
.style("border", "none")
.style("border-radius", "4px")
.style("pointer-events", "none");
legend.html("<span style='height:6px; width:6px; border-radius:50%; background-color:LightGrey; border:1px solid RebeccaPurple; display:inline-block; margin-left:5px; margin-right:9px; margin-bottom:1px;'></span>Articles with no citations<br><span style='height:7px; width:7px; border-radius:50%; background-color:RebeccaPurple; border:1px solid RebeccaPurple; display:inline-block; margin-left: 4px; margin-right:9px; margin-bottom:1px;'></span>Articles with one citation<br><span style='height:15px; width:15px; border-radius:50%; background-color:RebeccaPurple; border:1px solid RebeccaPurple; display:inline-block; margin-right:5px; margin-bottom:-4px;'></span>Articles with many citations");
///////////////////////////
// TOOLTIP
const tooltip = svg.append("foreignObject")
.attr("width",width)
.attr("height",height)
.style("pointer-events","none")
.append("xhtml:div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("width", "360px")
//.style("height", "28px")
.style("top", (margins + 70)+"px")
.style("left", (margins)+"px")
.style("padding", "10px")
.style("font", "16px sans-serif")
.style("line-height", "125%")
.style("vertical-align","middle")
.style("background", "white")
.style("border", "solid 1px RebeccaPurple")
.style("border-opacity","0.5")
.style("border-radius", "2px")
.style("pointer-events", "none");
///////////////////////
// ADD X-AXIS
const x_axis = d3.axisBottom()
.scale(xScale)
.tickFormat(d3.format("d"));
svg.append("g")
.attr("transform", "translate(0, "+(totalHeight-margins)+")")
.call(x_axis);
// ADD TITLE
svg.append("text")
.attr("x", margins)
.attr("y", margins)
.attr("text-anchor", "left")
.style("font", "18px sans-serif")
.text("How many articles about the future of work are published each year?");
// ADD SUB-TITLE
svg.append("text")
.attr("x", margins)
.attr("y", margins + 30)
.attr("text-anchor", "left")
.style("font", "14px sans-serif")
.text("And which ones are cited the most?");
// COUNT TOTAL PUBLICATIONS FOR EACH YEAR AND GET Y-POS FOR ANNOTATION
// initialize an array of annotations for each year
let annotations = [];
for (let i=startYear; i<=endYear; i++) {
annotations.push({"year":i, "pubs":0, "topY":totalHeight})
}
// iterate through data.nodes to count pubs per year and find the highest Y position
for (let i=0; i<nodes_JSON.length; i++) {
if (nodes_JSON[i].Year >= startYear && nodes_JSON[i].Year <= endYear) {
for (let j=0; j<annotations.length; j++) {
if (annotations[j].year == nodes_JSON[i].Year) {
annotations[j].pubs++
if (nodes_JSON[i].y < annotations[j].topY) annotations[j].topY = nodes_JSON[i].y
}
}
}
}
// ADD LABELS - COUNT FOR EACH COLUMN
svg.selectAll("text.annotations")
.data(annotations)
.enter()
.append("text")
.classed('annotations', true)
.attr("x", function(d) { return xScale(d.year)})
.attr("y", function(d) { return d.topY - 20})
.style("text-anchor","middle")
.style("font", "10px sans-serif")
.style("fill","grey")
.text(function(d){ return d.pubs });
return svg.node();
}