async function* draw_animated_map(
buffered_polygons,
polygon_orig,
waterline_index_start = 10,
reverse = false
) {
const opacity = d3
.scalePow()
.exponent(1)
.domain([0, buffered_polygons.length - 1])
.range([1, 0]);
const stroke_width = d3
.scalePow()
.exponent(3)
.domain([0, buffered_polygons.length - 1])
.range([1.4, 0.3]);
const geoGenerator = d3
.geoPath()
.projection(
d3
.geoMercator()
.fitSize([width, 600], buffered_polygons[buffered_polygons.length - 1])
);
let buffered_polygon_paths = [];
for (let i = 0; i < buffered_polygons.length; i++) {
let buffer_path = geoGenerator(buffered_polygons[i]);
let buffer_path_array = buffer_path.split("M");
buffer_path_array.sort(function(a, b) {
return b.length - a.length;
});
let buffer_path_longest = "M" + buffer_path_array[0];
buffered_polygon_paths.push(buffer_path_longest);
}
/////////////////////////
/// Draw original map ///
/////////////////////////
const svg = d3
.select(DOM.svg(width, 600))
.style("width", "100%")
.style("height", "auto");
const g = svg.append("g");
g.selectAll('path.waterLines')
.data(buffered_polygons)
.enter()
.append('g') // create g wrappers for the paths so we can apply concurrent animations (path and opacity) below
.attr('class', 'waterLine_g')
.attr('opacity', 1)
.append('path')
.attr("d", geoGenerator)
.attr("class", "waterLines")
.style('fill', 'none')
.style("stroke", 'teal');
g.append("path") // draw the original polygon on top of the waterlines
.datum(polygon_orig)
.attr("d", geoGenerator)
.attr("class", "land")
.style("fill", 'white')
.style("stroke", 'teal');
///////////////////////////
/// Define transitions ///
//////////////////////////
let n = waterline_index_start;
// for waterlines emitting outwards
if (!reverse) {
while (true) {
// remove the final waterline
g.selectAll('g.waterLine_g')
.filter((d, i) => i == buffered_polygons.length - 1)
.remove();
// create a new nth waterline
let n_plus_1th_DOM_node = g
.selectAll('g.waterLine_g')
.filter((d, i) => i == n)
.node();
g.insert('g')
// make the nth child
.each(function() {
this.parentNode.insertBefore(this, n_plus_1th_DOM_node);
})
.attr('class', 'waterLine_g')
.insert('path')
.datum(buffered_polygons[n])
.attr("d", geoGenerator)
.attr("class", "waterLines")
.attr('id', 'new')
.style('fill', 'none')
.style("stroke", 'teal');
// Transition the waterline paths
g.selectAll('path.waterLines')
.filter((d, i) => i > n) // don't include waterlines before n
.transition()
.duration(animation_interval)
.ease(d3.easeLinear)
.attrTween('d', function(d, i) {
var startPath = buffered_polygon_paths[i + n],
endPath = buffered_polygon_paths[i + 1 + n];
return flubber.interpolate(startPath, endPath);
});
//Transition the (new) final waterline, fade it out, and remove
// apply this transition to the parent g element, rather than the path element to avoid clashing animations https://bl.ocks.org/mbostock/6081914
g.selectAll('g.waterLine_g')
.filter((d, i) => i == buffered_polygons.length - 1)
.transition()
.duration(animation_interval)
.ease(d3.easeLinear)
.style('opacity', 0)
.remove();
await Promises.tick(animation_interval);
yield svg.node();
}
}
// waterlines going inwards
else {
while (true) {
// remove the n + 1th waterline
g.selectAll('g.waterLine_g')
.filter((d, i) => i == n + 1)
.remove();
// create new final waterline
g.append('g')
.attr('class', 'waterLine_g')
.append('path')
.datum(buffered_polygons[buffered_polygons.length - 1])
.attr("d", geoGenerator)
.attr("class", "waterLines")
.style('fill', 'none')
.style("stroke", 'teal')
.style('opacity', 1);
// Transition the waterline paths
g.selectAll('path.waterLines')
.filter((d, i) => i > n) // don't include waterlines before n
.transition()
.duration(animation_interval)
.ease(d3.easeLinear)
.attrTween('d', function(d, i) {
var startPath = buffered_polygon_paths[i + n + 1],
endPath = buffered_polygon_paths[i + n];
return flubber.interpolate(startPath, endPath);
});
//Transition the (new) final waterline, fade it in
// apply this transition to the parent g element, rather than the path element to avoid clashing animations https://bl.ocks.org/mbostock/6081914
g.selectAll('g.waterLine_g')
.filter((d, i) => i == buffered_polygons.length - 1)
.style('opacity', 0)
.transition()
.duration(animation_interval)
.ease(d3.easeLinear)
.style('opacity', 1);
await Promises.tick(animation_interval);
yield svg.node();
}
}
}