chart1 = function(data, month, year) {
const links = data.links.map(d => Object.create(d));
const nodes = data.nodes.map(d => Object.create(d));
let radiusFxn = d3[radiusMeasure]().domain(d3.extent(rDomain)).range(rNode)
let strokeFxn = d3[scaleMeasure]().domain(d3.extent(strokeDomain)).range(sWidth)
let colorFxn = d3.scaleOrdinal().domain(regionDomain).range(d3['schemeTableau10']);
let textFxn = d3[radiusMeasure]().domain(rDomain).range(textSize);
let xScale = d3.scaleLinear().domain(longDomain).range([200, width-200])
let yScale = d3.scaleLinear().domain(latDomain).range([height-100, 100])
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id).distance(25))
.force("charge", d3.forceManyBody().strength(-500))
.force('collision', d3.forceCollide().radius(100))
.force("center", d3.forceCenter(width / 1.85, height / 2))
.force('x', d3.forceX((d) => xScale(d.x)).strength(5))
.force('y', d3.forceY((d) => yScale(d.y)).strength(5));
const svg = d3.select(DOM.svg(width, height));
svg.append("text")
.attr("x", (width / 2))
.attr("y", 50)
.attr("text-anchor", "middle")
.style("font-size", "48px")
.attr("font-family", font)
.attr("fill", "#000")
.text(month + ' ' + year);
const gradient = DOM.uid();
svg.append("linearGradient")
.attr("id", gradient.id)
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", 0)
.attr("y1", height - 100)
.attr("x2", 0)
.attr("y2", 100)
.selectAll("stop")
.data(d3.ticks(0, 1, 10))
.join("stop")
.attr("offset", d => d)
.attr("stop-color", colors.interpolator());
const link = svg.append("g")
.selectAll("path")
.data(links)
.join("path")
.attr("stroke-width", d => strokeFxn(d[volMeasure]))
.attr("stroke", d => {console.log(d.source.region); return colorFxn(d.source.region)})
//.attr('stroke', '#e8e8e8')
// .attr("stroke", gradient)
.attr("fill", "transparent")
.attr("stroke-opacity", d => {
if (differStroke === true) {
if(d.source.id === d.target.id) {
return 0.5;
} else {
return 0.125;
}
}
return 0.2;
})
// .attr("marker-end", "url(#end)");
const node = svg.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 6)
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("r", d => radiusFxn(d.dayAve))
.attr("fill", d => colorFxn(d.region))
.call(drag(simulation))
const textElements = svg.append('g')
.selectAll('text')
.data(nodes)
.enter().append('text')
.text(node => node.id)
// .attr('font-size', 18)
.attr('font-size', node => {
if (textToggle === true) {
return textFxn(node.volume);
}
return 24;
})
.attr("font-family", font)
.attr("fill", "#000")
.attr('dx', -20)
.attr('dy', 4)
.attr('opacity', showText ? 1 : 0);
simulation.on("tick", () => {
link
.attr("d", function(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy)*arcness;
if (dx === 0 && dy ===0) {
// Fiddle with this angle to get loop oriented.
const xRotation = -45;
// Needs to be 1.
const largeArc = 1;
let sweep = 0
// Change sweep to change orientation of loop.
if (d.source.region === 'North-East' || d.source.region === 'East' || d.source.region === 'North') {
sweep = 1;
}
// Make drx and dry different to get an ellipse
// instead of a circle.
const drx = 30;
const dry = 30;
const x1 = d.source.x;
const y1 = d.source.y;
// For whatever reason the arc collapses to a point if the beginning
// and ending points of the arc are the same, so kludge it.
const x2 = d.target.x + 1;
const y2 = d.target.y + 1;
return "M" + x1 + "," + y1 + "A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " + x2 + "," + y2;
} else {
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}
});
textElements
.attr("x", node => node.x)
.attr("y", node => node.y)
// node
// .attr("cx", d => d.x)
// .attr("cy", d => d.y);
node.attr('transform', (d) => {
return 'translate(' + (d.x) + ',' + (d.y) + ')';
});
});
invalidation.then(() => simulation.stop());
return svg.node();
}