plainheart/echarts-extension-gmap

Can this extension implement polygons and polylines on Google Map?

Closed this issue · 9 comments

Can this extension implement polygons and polylines on Google Map?

Also how to add an api key when using webpack? Thank you!

Can this extension implement polygons and polylines on Google Map?

Yes, you can refer to the official example about Baidu Map.

Also how to add an api key when using webpack?

You can add a script to your HTML template or use a google-map-loader in your js code. For example, https://github.com/davidkudera/google-maps-loader.

Or wrap simply a script loader like this.

const mapScriptURL = 'https://maps.googleapis.com/maps/api/js?key=your api key from google map platform'

function isGoogleMapAPILoaded() {
    return typeof google !== 'undefined' && typeof google.maps !== 'undefined'
}

function loadGoogleMapScript() {
    return new Promise((resolve, reject) => {
      // if google map API script has loaded, no need to insert it again
      if (isGoogleMapAPILoaded()) {
        resolve(google)
      } else {
        const scriptNode = document.createElement('script')
        scriptNode.setAttribute('type', 'text/javascript')
        scriptNode.setAttribute('charset', 'utf-8')
        scriptNode.setAttribute('src', mapScriptURL)
        scriptNode.setAttribute('id', 'google-map-api-script')
        scriptNode.onload = () => {
          if (isGoogleMapAPILoaded()) {
            resolve(google)
          } else {
            reject('failed to load google map API script')
          }
        }
        scriptNode.onerror = e => {
          reject(e)
        }
        // check again before inserting script
        if (isGoogleMapAPILoaded()) {
          resolve(google)
        } else {
          document.head.appendChild(scriptNode)
        }
      }
    })
}

Then you can use the loader in your code,

loadGoogleMapScript().then(google => {
   console.log('google map script loaded', google)
   // to create echarts instance and get google map instance
   const chart = echarts.init(document.getElementById('chart-container'));
   chart.setOption(option);
   // get google map instance
   const gmap = chart.getModel().getComponent('gmap').getGoogleMap();
   // to add a marker
   const marker = new google.maps.Marker({ position: gmap.getCenter() });
   marker.setMap(gmap);
})

Thanks! I'm really appreciated. Currently I'm using your extension under vue-echarts environment. I loaded the map correctly but it failed to display scatter chart on the map using your demo code. Also when I add another tooltip component, the map is just crashed which I don't know why.

Could I know if you are assigning the ECharts instance object with Vue ref? If so, I'd like to suggest using a normal variable without any wrapper.

let chart;
chart = echarts.init(document.getElementById('chart-container'));

No I didn't use ref. It's just <v-chart :option="this.option"></v-chart>. All components and series can be set in option.

I tried the example from vue-echarts, it works.

<template>
  <v-chart class="chart" :option="option" />
</template>

<script>
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { ScatterChart } from "echarts/charts";
import {
  TitleComponent,
  TooltipComponent
} from "echarts/components";
// import google map extension
import "echarts-extension-gmap";
import VChart from "vue-echarts";
import { ref, defineComponent, onMounted } from "vue";

use([
  CanvasRenderer,
  ScatterChart,
  TitleComponent,
  TooltipComponent
]);

function isGoogleMapAPILoaded() {
    return typeof google !== 'undefined' && typeof google.maps !== 'undefined'
}

function loadGoogleMapScript() {
    const mapScriptURL = 'https://maps.googleapis.com/maps/api/js?key=you key';
    return new Promise((resolve, reject) => {
      // if google map API script has loaded, no need to insert it again
      if (isGoogleMapAPILoaded()) {
        resolve()
      } else {
        const scriptNode = document.createElement('script')
        scriptNode.setAttribute('type', 'text/javascript')
        scriptNode.setAttribute('charset', 'utf-8')
        scriptNode.setAttribute('src', mapScriptURL)
        scriptNode.setAttribute('id', 'google-map-api-script')
        scriptNode.onload = () => {
          if (isGoogleMapAPILoaded()) {
            resolve()
          } else {
            reject('failed to load google map API script')
          }
        }
        scriptNode.onerror = e => {
          reject(e)
        }
        // check again before inserting script
        if (isGoogleMapAPILoaded()) {
          resolve()
        } else {
          document.head.appendChild(scriptNode)
        }
      }
    })
}

export default defineComponent({
  name: "HelloWorld",
  components: {
    VChart
  },
  setup: () => {
    const option = ref();

    onMounted(async () => {
      // load api
      await loadGoogleMapScript()

      option.value = {
        title: {
          text: "Traffic Sources",
          left: "center"
        },
        tooltip: {
          trigger: "item"
        },
        legend: {
          orient: "vertical",
          left: "left",
          data: ["Direct", "Email", "Ad Networks", "Video Ads", "Search Engines"]
        },
        gmap: {
          center: [108.39, 39.9],
          zoom: 4
        },
        series: [
          {
            name: "Scatter",
            type: "scatter",
            coordinateSystem: "gmap",
            data: [
              [120, 30, 50]
            ],
            encode: {
              value: 2
            }
          }
        ]
      }
    })

    return { option };
  }
});
</script>

<style scoped>
.chart {
  height: 100vh;
}
</style>

<style>
body {
  margin: 0;
}
</style>

Actually I use Vue2 and just tag script in index.html to get permission like this:
<script async src="https://maps.googleapis.com/maps/api/js?key=..."> </script>
Also I think I didn't define the async vue component like you do.
Is that the potential reason?

I think I found where is wrong. Map needs to be specified height, that is:
<v-chart class="chart" :option="option" />
<style scoped> .chart { height: 100vh; } </style>
Otherwise scatter or other overlays won't be displayed.

That's great. Glad to see your problem solved.