travel-legs-worldmap.js 3.05 KB
/**
 * Draws a SVG in the DOM element identified by `containerSelector`.
 *
 * Issues
 * ------
 *
 * - No Zoom (spent 4h on this already)
 * - No animations (wait 'til it's polished)
 *
 * @param containerSelector string
 *   CSS selector, like "#d3viz"
 * @param worldDataUrl
 *   A JSON file with reusable world data.
 *   @see /static/public/data/world-earth.geojson
 * @param travelsDataUrl
 *   A CSV file with rows of
 *   - origin_lon
 *   - origin_lat
 *   - destination_lon
 *   - destination_lat
 */
function draw_travel_legs_worldmap(containerSelector, worldDataUrl, travelsDataUrl) {

    document.addEventListener('DOMContentLoaded', () => {
        const margin = {top: 0, right: 0, bottom: 0, left: 0};
        // var width = $(containerSelector).parent().width();
        // var height = width - margin.top - margin.bottom;
        // let width = width - margin.left - margin.right;
        //{#var height = Math.max(300, 600) - margin.top - margin.bottom;#}
        //{#var width = Math.max(880, $(containerSelector).parent().width());#}

        const size_ratio = 0.85;
        let width = 629.0 * size_ratio;
        let height = 604.0 * size_ratio;
        //{#width = 500.0;#}
        //{#height = 400.0;#}

        let offset_x = 0.0;
        let offset_y = 0.0;

        const svg = d3.select(containerSelector)
            .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom);

        const projection = d3.geoMercator()
            .scale(85)
            .translate([width / 2.0 + offset_x, height / 2.0 + offset_y]);

        const geopath = d3.geoPath().projection(projection);

        function draw_from_data(worldData, legsData) {
            const link = [];
            legsData.forEach(function (row) {
                source = [+row.origin_lon, +row.origin_lat];
                target = [+row.destination_lon, +row.destination_lat];
                topush = {type: "LineString", coordinates: [source, target]};
                link.push(topush);
            });

            svg.append("g")
                .selectAll("path")
                .data(worldData.features)
                .enter()
                .append("path")
                .attr("fill", "#b8b8b8")
                .attr("d", geopath)
                .style("stroke", "#fff")
                .style("stroke-width", 0);

            svg.selectAll("myPath")
                .data(link)
                .enter()
                .append("path")
                .attr("d", geopath)
                //            .attr("d", function (d) {
                //                return geopath(d);
                //            })
                .style("fill", "none")
                .style("stroke", "#69b3a2")
                .style("stroke-width", 2);

        }

        const worldDataPromise = d3.json(worldDataUrl);
        const travelsDataPromise = d3.csv(travelsDataUrl);
        Promise.all([worldDataPromise, travelsDataPromise]).then((values) => {
            draw_from_data(values[0], values[1]);
        });

    });

}