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]);
let buffered_polygon_paths = [];
for (let i = 0; i < buffered_polygons.length; i++) {
let buffer_path = path(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", path)
.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", path)
.attr("class", "land")
.style("fill", "white")
.style("stroke", "teal");
///////////////////////////
/// Define transitions ///
//////////////////////////
let n = waterline_index_start;
// for waterlines emitting outwards
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", path)
.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();
}
}