Search code examples
frontendvuejs3amchartsamcharts5

Empty Div Preventing Interaction with amCharts5 MapChart on Vue3


I decided to dip my toes in Vue and have had an idea for a website for a while which I'd like to use amCharts5 for.

I had some issues initially as all the info I could find was related to Vue2, but I think I've somewhat wrapped my head around Vue3 and its composition API.

The MapChart is created, however there is always a div slapped on top of it which prevent any interaction. If I delete this element via DevTools, the MapChart becomes interactive.

I've tried debugging this and commenting sections of the code out, regardless this div is always created. And I simply can't figure out if it's injected by Vue or if amCharts 5 is the culprit.

le bug

The highlighted element is the one I must delete for it to become interactive.

Here's how the component is setup;

<template>
  <div class="testClass" ref="chartdiv">
  </div>
</template>

<script setup lang="ts">
  import * as am5 from "@amcharts/amcharts5";
  import * as am5map from "@amcharts/amcharts5/map";
  import am5geodata_worldLow from "@amcharts/amcharts5-geodata/worldLow";
  import am5themes_Animated from '@amcharts/amcharts5/themes/Animated';
  import { ref, onMounted, onUnmounted } from "vue";

  const chartdiv = ref<HTMLElement | null>()
  var root!: am5.Root;

  onMounted(() => {
    if (chartdiv.value) {
      // Create the Root
      var root = am5.Root.new(chartdiv.value);
      
      // Setup the MapChart
      var chart = root.container.children.push(
        am5map.MapChart.new(root, {
          panX: "rotateX",
          panY: "rotateY",
          projection: am5map.geoOrthographic(),
          centerMapOnZoomOut: false
        })
      );

      // Setup Animations
      root.setThemes([
        am5themes_Animated.new(root)
      ]);

      // Create MapPolygons
      var polygonSeries = chart.series.push(
        am5map.MapPolygonSeries.new(root, {
          geoJSON: am5geodata_worldLow
        })
      );

      // Setup MapPolygon Styling
      polygonSeries.mapPolygons.template.setAll({
        tooltipText: "{name}",
        fill: am5.color("#909090")
      });
      
      // Setup MapPolygon Hover Styling
      polygonSeries.mapPolygons.template.states.create("hover", {
        fill: am5.color("#FF0000"),
        stroke: am5.color("#00FF00"),
        strokeWidth: 2
      });

      polygonSeries.mapPolygons.template.events.on("click", function(event) {
        //console.log("Clicked: {0}", event.target);
      });

      // Setup Background
      var backgroundSeries = chart.series.unshift(
        am5map.MapPolygonSeries.new(root, {})
      );

      backgroundSeries.mapPolygons.template.setAll({
        fill: am5.color(0x2c84d0),
        stroke: am5.color(0x2c84d0)
      });

      backgroundSeries.data.push({
        geometry: am5map.getGeoRectangle(90, 180, -90, -180)
      });
    }
  });

  onUnmounted(() => {
    if (root) {
      root.dispose();
    }
  });
</script>

<style scoped>
  .testClass {
    width: 50vw;
    height: 50vh;
  }
</style>

Solution

  • When you create a Vite-powered Vue project, it automatically creates a bunch of CSS files for you. One of those is base.css.

    Inside this file, you'll find these lines which causes all the headache;

    *,
    *::before,
    *::after {
      box-sizing: border-box;
      margin: 0;
      position: relative;
      font-weight: normal;
    }
    

    Removing those lines will fix the issue.