Animated lines on a world map

author(s): Mustapha Mekhatria

by Black Label

HTML

<script src="https://code.highcharts.com/maps/highmaps.js"></script>
<script src="https://code.highcharts.com/maps/modules/exporting.js"></script>
<script src="https://code.highcharts.com/maps/modules/offline-exporting.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<script src="https://code.highcharts.com/maps/modules/series-on-point.js"></script>

<div id="container"></div>

CSS

#container {
    min-width: 320px;
    max-width: 800px;
    height: 500px;
    margin: 1em auto;
}

.animated-line {
    stroke-dasharray: 8;
    stroke-dashoffset: 10;
    animation: dash 5s linear infinite;
}

@keyframes dash {
    from {
        stroke-dashoffset: 100;
    }

    to {
        stroke-dashoffset: 20;
    }
}

JavaScript

(async () => {
  const topology = await fetch(
    'https://code.highcharts.com/mapdata/custom/world-highres.topo.json'
  ).then(response => response.json());

  const data = [
    // country, s, f
    ['PL', 15, 3],
    ['NO', 20, 2],
    ['UA', 10, 10],
    ['DE', 10, 15],
    ['BY', 1, 2],
    ['FR', 20, 20],
    ['CZ', 20, 0],
    ['SE', 15, 10],
    ['BR', 10, 20],
    ['AU', 14, 12],
    ['NZ', 10, 5],
    ['NG', 15, 10],
    ['MA', 15, 10],
    ['DZ', 10, 20]
  ];

  data.forEach(o => {
    o.push(o[1] - o[2]);
  });

  const chart = Highcharts.mapChart('container', {
    chart: {
      map: topology
    },

    legend: {
      enabled: false
    },

    mapView: {
      fitToGeometry: {
        type: 'MultiPoint',
        coordinates: [
          // Alaska west
          [-164, 54],
          // Greenland north
          [-35, 84],
          // New Zealand east
          [179, -38],
          // Chile south
          [-68, -55]
        ]
      }
    },

    colorAxis: {
      dataClasses: [{
        from: -15,
        to: -Number.MIN_VALUE,
        color: '#faa',
        name: 'Successes'
      }, {
        from: 0,
        to: 0,
        color: '#ddd',
        name: 'Neutral'
      }, {
        from: Number.MIN_VALUE,
        to: 15,
        color: '#adf',
        name: 'Failures'
      }]
    },

    series: [{
      keys: ['id', 'successes', 'failures', 'value'],
      joinBy: ['iso-a2', 'id'],
      data: data,
    }]
  });

  chart.series[0].points.forEach(country => {
    if (!country.isNull) {
      chart.addSeries({
        type: 'pie',
        name: country.id,
        zIndex: 6,
        size: 15,
				dataLabels: {
					enabled: false
				},
        onPoint: {
          id: country.id
        },
        states: {
          inactive: {
            enabled: false
          }
        },
        data: [{
          name: 'Successes',
          y: country.successes,
          color: '#adf'
        }, {
          name: 'Failures',
          y:...