nukalov
nukalov

Reputation: 1357

Dynamically Update amCharts 4 World Map with Animation (Javascript)?

I am trying to create a map with amCharts, that has the animated circles like in the example they provide in the page below. If I add the data in the main function (code below - on am4core.ready(..)) it works fine, but I want to dynamically add data to my map and still retain the animation.

I have a separate function that polls data every second or so (second code below), and updates imageSeries with the new data. This works fine, and adds a circle to my map, but it does not animate it.

Original Code Example: https://www.amcharts.com/demos/map-with-pulsating-bullets/

My Code:

<script>
  var colorSet = new am4core.ColorSet();
  var imageSeriesData = [];
  var chart;
  var imageSeries;

  am4core.ready(function() {
    am4core.useTheme(am4themes_animated);
    chart = am4core.create("mapcontainer", am4maps.MapChart);
    chart.geodata = am4geodata_worldLow;
    chart.projection = new am4maps.projections.Miller();
    var polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
    polygonSeries.exclude = ["AQ"];
    polygonSeries.useGeodata = true;
    var polygonTemplate = polygonSeries.mapPolygons.template;
    polygonTemplate.tooltipText = "{name}";
    polygonTemplate.polygon.fillOpacity = 0.6;
    var hs = polygonTemplate.states.create("hover");
    hs.properties.fill = chart.colors.getIndex(0);
    imageSeries = chart.series.push(new am4maps.MapImageSeries());
    imageSeries.mapImages.template.propertyFields.longitude = "longitude";
    imageSeries.mapImages.template.propertyFields.latitude = "latitude";
    imageSeries.mapImages.template.tooltipText = "{title}";
    imageSeries.mapImages.template.propertyFields.url = "url";
    var circle = imageSeries.mapImages.template.createChild(am4core.Circle);
    circle.radius = 5;
    circle.propertyFields.fill = "color";
    var circle2 = imageSeries.mapImages.template.createChild(am4core.Circle);
    circle2.radius = 5;
    circle2.propertyFields.fill = "color";
    circle2.propertyFields.scale = "scale";
    circle2.events.on("inited", function(event) {
      animateBullet(event.target);
    });

    function animateBullet(circle) {
      var animation = circle.animate([{
        property: "scale",
        from: 1,
        to: circle.scale
      }, {
        property: "opacity",
        from: 1,
        to: 0
      }], 1000, am4core.ease.circleOut);
      animation.events.on("animationended", function(event) {
        animateBullet(event.target.object);
      })
    }

    imageSeries.data = imageSeriesData;

  });
</script>

Function that pushes the data to imageSeries.data and to the map:

imageSeriesData.push({
  "title": data.country,
  "latitude": latlong[data.country].latitude,
  "longitude": latlong[data.country].longitude,
  "color":colorSet.next()
});

imageSeries.data = imageSeriesData;

This code above works, and does update the map. But, it does not animate the dot like in the example they provided.

What am I missing here? How can I push data dynamically to the map and also animate the little dots like in the example they provided? I've tried also moving the animateBullet(..) function to a global location, still nothing.

Any ideas?

Data Concepts: https://www.amcharts.com/docs/v4/concepts/data/

Unfortunately read through this document above, and it doesn't provide anything regarding World Maps.

Upvotes: 3

Views: 1603

Answers (1)

nukalov
nukalov

Reputation: 1357

I figured it out... I had exposed a few global variables at the top of my script so that they would be accessible to my update function. But, what I didn't realize is:

  1. I was incorrectly declaring colorSet, before am4core was initialized inside the am4core.ready(..) function.
  2. The original code example from their website declares colorSet after the circles. I had mistakenly completely removed that declaration.

Bad Code:

<script>
  var colorSet = new am4core.ColorSet();
  var imageSeriesData = [];
  var chart;
  var imageSeries;
...

Now new code and working, still exposing imageSeries (for data updates) and colorSet (for entry that includes color variable):

<script>
  var imageSeries;
  var colorSet;
  am4core.ready(function() {
    am4core.useTheme(am4themes_animated);
    var chart = am4core.create("mapcontainer", am4maps.MapChart);
    chart.geodata = am4geodata_worldLow;
    chart.projection = new am4maps.projections.Miller();
    var polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
    polygonSeries.exclude = ["AQ"];
    polygonSeries.useGeodata = true;
    var polygonTemplate = polygonSeries.mapPolygons.template;
    polygonTemplate.tooltipText = "{name}";
    polygonTemplate.polygon.fillOpacity = 0.6;
    var hs = polygonTemplate.states.create("hover");
    hs.properties.fill = chart.colors.getIndex(0);
    imageSeries = chart.series.push(new am4maps.MapImageSeries());
    imageSeries.mapImages.template.propertyFields.longitude = "longitude";
    imageSeries.mapImages.template.propertyFields.latitude = "latitude";
    imageSeries.mapImages.template.tooltipText = "{title}";
    imageSeries.mapImages.template.propertyFields.url = "url";
    var circle = imageSeries.mapImages.template.createChild(am4core.Circle);
    circle.radius = 4;
    circle.propertyFields.fill = "color";
    var circle2 = imageSeries.mapImages.template.createChild(am4core.Circle);
    circle2.radius = 4;
    circle2.propertyFields.fill = "color";
    circle2.events.on("inited", function(event) {
      animateBullet(event.target);
    })
    function animateBullet(circle) {
      var animation = circle.animate([{
        property: "scale",
        from: 1,
        to: 10
      }, {
        property: "opacity",
        from: 1,
        to: 0
      }], 1000, am4core.ease.circleOut);
      animation.events.on("animationended", function(event) {
        animateBullet(event.target.object);
      })
    }

    colorSet = new am4core.ColorSet();

    imageSeries.data = [];

  });
</script>

I hope this helps anyone that's experiencing the same issue!

Upvotes: 0

Related Questions