使用vue-google-maps套件實作地圖(二)


Posted by ChloeLin on 2021-12-25

上回講完在網頁上放置地圖及 marker ,這回來講講如何放置多個 marker 及客製化地標資訊。

在地圖上放置多個 marker

這個簡單,只要在 data 中的 markers 放置一組的 position 陣列,並用 v-for 放到 template 中就可以囉!

<template>
  <GmapMap
    :center="center"
    :zoom="15"
    :options="options"
    style="width: 100%; height: 600px"
  >
    <GmapMarker
      v-for="(m,i) in markers"
      :key="i"
      :position="m.position"
      :clickable="false"
      :draggable="false"
    />
  </GmapMap>
</template>
<script>
export default {
  name: "AddGoogleMap",
  data() {
    return {
      markers: [
        { position: { lat: 25.033671, lng: 121.564427 } },
        { position: { lat: 25.0325917, lng: 121.5624999 } },
        // 可新增多個地點。
      ],
      center: { lat: 25.033671, lng: 121.564427 },
      options: {
        mapTypeControl: false,
        scaleControl: false,
        streetViewControl: false,
        fullscreenControl: false,
        disableDefaultUI: true,
        scrollwheel: true,
        clickableIcons: false,
      },
    };
  },
};
</script>

成果會長這樣:

放置地標資訊 ( InfoWindow )

<template>
    <GmapMap
      :center="center"
      :zoom="15"
      :options="options"
      style="width: 100%; height: 600px"
    >
      <GmapInfoWindow
        :position="infoWindowPos"
        :opened="infoWinOpen"
        :options="infoOptions"
        @closeclick="infoWinOpen = false"
      >
      </GmapInfoWindow>
      <GmapMarker
        v-for="(m, i) in markers"
        :key="i"
        :position="m.position"
        :clickable="true"
        :draggable="false"
        @click="toggleInfoWindow(m, i)"
      />
    </GmapMap>
</template>

我們先來介紹 GmapInfoWindow 的屬性。

  • position:要有地標資訊的地方。
  • opened:是否開啟地標。
  • options:主要有三個常用屬性。
    • maxWidth:設定最大寬度。
    • content:地標資訊的內容,支援 HTML 語法。
    • pixelOffset:位移多少 {width, height} 。
  • closeclick:按下關閉視窗時要做的動作。
    更多Map控制內容可以參考 Google Map 官方文件

我們來看看 data 的設定:

  data() {
    return {
      markers: [
        {
          position: { lat: 25.033671, lng: 121.564427 },
          infoText:
            "<div class='img'><img src='https://www.taiwan.net.tw/att/1/big_scenic_spots/pic_7927_32.jpg'  alt='台北101'></div><h4 style='font-size: 1rem;'>台北101</h4>",
        },
        {
          position: { lat: 25.0325917, lng: 121.5624999 },
          infoText: "<div class='img'><img src='https://photo.travelking.com.tw/scenery/1F8576A4-EFD5-494E-B117-9F89E5A9A9C6_e.jpg'  alt='捷運世貿站'></div><h4 style='font-size: 1rem;'>捷運世貿站</h4>",
        },
      ],
      center: { ... },
      options: { ... },
      infoWindowPos: null,
      infoWinOpen: false,
      currentIdx: null,

      infoOptions: {
        maxWidth: 200,
        content: "",
        pixelOffset: {
          width: 0,
          height: -40,
        },
      },
    };
  }

infoText:markers 中的每個項目都增加了 infoText ,表示之後要呈現的內容。
infoWindowPos:用來裝要呈現地標資訊的座標。
infoWinOpen:是否要開啟地標資訊。
currentiIdx:要開啟地標資訊的是誰。

補充:我有另外地標資訊中的圖片一組CSS。

.img {
    width: 150px;
    height: 120px;
    padding: 4px;
    overflow: hidden;
    img {
      height: 100%;
      width: auto;
    }

有了這些資訊之後,透過在 GmapMarker 上綁定 click 事件,便可以知道點擊的地點及Index資訊。

接著在 methods 新增 function toggleInfoWindow,點擊一次會開啟視窗,如果兩次都點擊同個地點,則會關閉視窗。

  methods: {
    toggleInfoWindow: function (marker, idx) {
      this.infoWindowPos = marker.position;
      this.infoOptions.content = marker.infoText;
      if (this.currentIdx == idx) {
        this.infoWinOpen = !this.infoWinOpen;
      } else {
        this.infoWinOpen = true;
        this.currentIdx = idx;
      }
    },
  },

鏘鏘——完成效果請看!

完整 script 請見以下:

<script>
export default {
  name: "AddGoogleMap",
  data() {
    return {
      markers: [
        {
          position: { lat: 25.033671, lng: 121.564427 },
          infoText:
            "<div class='img'><img src='https://www.taiwan.net.tw/att/1/big_scenic_spots/pic_7927_32.jpg'  alt='台北101'></div><h4 style='font-size: 1rem;'>台北101</h4>",
        },
        {
          position: { lat: 25.0325917, lng: 121.5624999 },
          infoText: "<div class='img'><img src='https://photo.travelking.com.tw/scenery/1F8576A4-EFD5-494E-B117-9F89E5A9A9C6_e.jpg'  alt='捷運世貿站'></div><h4 style='font-size: 1rem;'>捷運世貿站</h4>",
        },
      ],
      center: { lat: 25.033671, lng: 121.564427 },
      options: {
        mapTypeControl: false,
        scaleControl: false,
        streetViewControl: false,
        fullscreenControl: false,
        disableDefaultUI: true,
        scrollwheel: true,
        clickableIcons: false,
      },
      infoWindowPos: null,
      infoWinOpen: false,
      currentIdx: null,

      infoOptions: {
        maxWidth: 200,
        content: "",
        pixelOffset: {
          width: 0,
          height: -40,
        },
      },
    };
  },
  methods: {
    toggleInfoWindow: function (marker, idx) {
      this.infoWindowPos = marker.position;
      this.infoOptions.content = marker.infoText;
      if (this.currentIdx == idx) {
        this.infoWinOpen = !this.infoWinOpen;
      } else {
        this.infoWinOpen = true;
        this.currentIdx = idx;
      }
    },
  },
};
</script>

#google map API #Vue #Vue.js #vue2-google-maps #Front-End #前端







Related Posts

用 React + Redux 做一個 todo list 吧

用 React + Redux 做一個 todo list 吧

為什麼需要 React / 思考模式的差異 / state vs props

為什麼需要 React / 思考模式的差異 / state vs props

與 DDoS 奮戰:nginx, iptables 與 fail2ban

與 DDoS 奮戰:nginx, iptables 與 fail2ban


Comments