Search code examples
angulartypescriptamchartsamcharts4

Amcharts4 marker html-tooltips without hover event


I am using this example to put map markers on click and my goal is displaying mapMarker.tooltipHTML elements by default, without hovering on them. Any alternatives such as creating html markers with are welcomed.


Solution

  • Well there are a couple of steps involved to getting Tooltips to work the way you want out of the box. Firstly, tooltips are usually something of a singleton, instead of one per polygon or per mapImage, they actually share the one on their series. So each has to use their own tooltip (for the most part, mapImage below is the imageSeries.mapImages.template):

    mapImage.tooltip = new am4core.Tooltip();
    

    Next, the condition that enables the tooltip, normally on hover, is if there's tooltipText or tooltipHTML set that isn't an empty string.

    mapImage.tooltipText = "Latitude: {latitude}\nLongitude: {longitude}";
    

    Tooltips showing up on hover is the default behavior, the easiest way to prevent that is to disable mouse interactions on the mapImage:

    mapImage.interactionsEnabled = false;
    

    Now, once a marker is created, we'll just show the tooltip:

    mapImage.events.once("inited", function(event) {
      event.target.showTooltip();
    });
    

    By default the tooltip position is already set to "fixed" and its pointerOrientation to "vertical", we just need it to show up above the marker, which in this example is 32x32 px, scaled down 30%, so we just shift it up by 32 * .7 via the mapImage's tooltipY property:

    mapImage.nonScaling = true; // this is also necessary so the size/vertical shift is predictably the same
    mapImage.tooltipY = -32 * .7;
    

    Last but not least, the tooltips don't maintain their position on zoom, so we'll have to do that ourselves by listening for zoom changes, converting map images' lat/long coords to chart x/y coords, and passing that to each tooltip:

    chart.events.on("zoomlevelchanged", function() {
      imageSeries.mapImages.each(function(mapImage) {
        var point = chart.geoPointToSVG({ latitude: mapImage.latitude, longitude: mapImage.longitude });
        mapImage.tooltip.moveTo({ x: point.x, y: point.y - (32 * .7)});
      });
    });
    

    Here's a demo:

    https://codepen.io/team/amcharts/pen/698eb4a11c35733850fbc084631bfc21

    Addendum (2019-04-11):

    You can also bind the latitude/longitude properties to data and create mapImages that way via the addData method, e.g.

    var mapImage = imageSeries.mapImages.template;
    mapImage.propertyFields.latitude = "latitude";
    mapImage.propertyFields.longitude = "longitude";
    
    // You can even start off with some markers at the onset
    // From our Animations along lines demo: https://www.amcharts.com/demos/animations-along-lines/
    imageSeries.data = [
      { "latitude": 48.8567, "longitude": 2.3510, "name": "Paris"},
      { "latitude": 43.8163, "longitude": -79.4287, "name": "Toronto"},
      { "latitude": 34.3, "longitude": -118.15, "name": "Los Angeles"},
      { "latitude": 23, "longitude": -82, "name": "Havana"},
    ];
    
    chart.seriesContainer.events.on("hit", function(ev) {
      var coords = chart.svgPointToGeo(ev.svgPoint);
      // var marker = imageSeries.mapImages.create();  
      // marker.latitude = coords.latitude;
      // marker.longitude = coords.longitude;
      imageSeries.addData({
        latitude: coords.latitude,
        longitude: coords.longitude,
      });
    });
    

    If you want to remove markers from the beginning of the data array, use the removeData method. If you want to modify the data array using Array.splice, if the array is not empty afterwards, you'll have to run imageSeries.invalidateData() to update the view. If the array will be empty, it's better to just set imageSeries.data = undefined instead. Also keep in mind the addData method has a 2nd parameter that also removes items from the beginning of the array.

    Another note, you'll have to manually dispose the marker tooltips in their "beforedisposed" event.

    Here's an updated and improved demo that includes some bug fixes:

    https://codepen.io/team/amcharts/pen/fee1cb6db8971ec3eff6541ad52bab6d