drawChart = function(){
var svg = d3.select("svg")
.attr("width", width)
.attr("height", height);
var sankey = d3.sankey()
.nodeWidth(15)
.nodePadding(10)
.size([width, height]);
var formatNumber = d3.format(",.0f"),
format = function(d) { return formatNumber(d) + " TWh"; }
var path = sankey.link();
var freqCounter = 1;
energy.links.forEach(function(d){
d.o_value = d.value;
d.value = 1;
})
energy.nodes.forEach(function(d,i){
d.color = colors[i%colors.length]
})
sankey
.nodes(energy.nodes)
.links(energy.links)
.layout(32);
var link = svg.append("g").selectAll(".link")
.data(energy.links)
.enter().append("path")
.attr("class", "link")
.attr("d", path)
.style("stroke-width", function(d){
return Math.max(1, d.dy);
})
.sort(function(a,b) {return b.dy - a.dy});
link.append("title")
.text(function(d) {return d.source.name + " -> " + d.target.name + "\n" + format(d.o_value);});
var node = svg.append("g").selectAll(".node")
.data(energy.nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d){ return "translate(" + d.x + ", " + d.y + ")";})
.call(d3.drag()
.on("drag", function (event,d){
d.x = event.x
d.y = event.y
d3.select(this).attr("transform", d => `translate(${d.x},${d.y})`);
sankey.relayout();
link.attr("d",path);}
));
node.append("rect")
.attr("height", function(d) {return d.dy;})
.attr("width", sankey.nodeWidth())
.style("fill", function(d,i) {return d.color})
.style("rx", 5)
.style("stroke", "none");
var linkExtent = d3.extent(energy.links, function(d) {return d.o_value});
var frequencyScale = d3.scaleLinear().domain(linkExtent).range([0.05, 1]);
var particleSize = d3.scaleLinear().domain(linkExtent).range([1,5]);
energy.links.forEach(function(link) {
link.freq = frequencyScale(link.o_value);
link.particleSize = 2;
link.particleColor = d3.scaleLinear().domain([0,1])
.range([link.source.color, link.target.color])
});
var particles = [];
function tick(elapsed, time) {
//Remove complete particles
particles = particles.filter(function(d) {return d.current < d.path.getTotalLength()});
function particleEdgeCanvasPath(elapsed) {
var context = d3.select("canvas").node().getContext("2d")
context.clearRect(0,0,width,height);
context.fillStyle = "gray";
context.lineWidth = "1px";
for (var x in particles) {
//Particle Progress: difference between current time, and time of creation
var currentTime = elapsed - particles[x].time;
//Progress Adjusted for speed?
particles[x].current = currentTime * 0.15 * particles[x].speed
var currentPos = particles[x].path.getPointAtLength(particles[x].current);
context.beginPath();
context.fillStyle = particles[x].link.particleColor(0);
context.arc(currentPos.x, currentPos.y + particles[x].offset, particles[x].link.particleSize, 0, 2*Math.PI);
context.fill();
}
};
//Generate particle data
d3.selectAll("path.link")
.each(function(d) {
for (var x=0; x<2; x++) {
//Y jitter
var offset = (Math.random() - .5) * (d.dy - 4);
//Generate particles based on frequency distribution
if (Math.random() < d.freq) {
var length = this.getTotalLength();
particles.push({link: d, time: elapsed, offset: offset, path: this, length: length, animateTime: length, speed: 0.5 + (Math.random())})
}
}
})
particleEdgeCanvasPath(elapsed)
};
var t = d3.timer(tick, 1000);
}