2018-04-26

幾個簡單的 Google Maps JavaScript API 使用範例

Google Maps 提供了原生 JavaScript API,可以在網站或 Web App 上呈現視覺化的地圖及豐富的地圖功能,例如景點位置、路線規劃與街景服務等。就來試試看有趣的 Google Maps JavaScript API 吧…


本篇範例使用到高雄市觀光景點位置JSON資料,下載和範例程式放在一起即可。
以符號(symbol)和大小呈現資料
可以利用 google.maps.SymbolPath 提供的符號(symbol)並運用大小(scale)屬性來呈現資料的位置和數值,像是圓圈的大小,常見的例子像呈現地震位置和規模。
使用時須在 google.maps.Marker 物件中加入 icon:{path: google.maps.SymbolPath.},符號相關屬性的設定請參考《Google Maps JavaScript API Documentation - 符號》:
var marker = new google.maps.Marker({
   position: latLng,  // 圖點位置
   icon: {
      path: google.maps.SymbolPath.CIRCLE,  // 使用圖圈圖形
      strokeColor: ,   // 線條顏色
      strokeWeight: ,  // 線條粗細
      fillColor: ,     // 填充顏色
      fillOpacity: ,   // 填充透明度
      scale:           // 圖形大小
   },
});
以下為高雄市觀光景點位置JSON資料,呈現符號(symbol)和大小的範例,因為在這個例子中沒有特別的數值內容,我們取 1~10 的亂數代表該筆資料的規模。注意需申請您的 Google API 金鑰,以替代 YOUR_API_KEY。
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script>
    function initMap() {
        if (navigator.geolocation) {
            var options={timeout:10000};
            navigator.geolocation.getCurrentPosition(showPosition, showError, options);
        } else {
            var x = document.getElementById("demo");
            x.innerHTML = "Geolocation is not supported by this browser.";
        }
    }

    function showPosition(position) {
        lat = position.coords.latitude;
        lon = position.coords.longitude;
        latlon = new google.maps.LatLng(lat, lon)
        mapholder = document.getElementById("mapholder")
        mapholder.style.height = "500px";
        mapholder.style.width = "1100px";

        var myOptions = {
            center:latlon,zoom:16,
            mapTypeId:google.maps.MapTypeId.ROADMAP,
            mapTypeControl:false,
            navigationControlOptions:{style:google.maps.NavigationControlStyle.SMALL}
        }
        
        var map = new google.maps.Map(document.getElementById("mapholder"), myOptions);
        // Load json data from JSON file
        var xmlhttp = new XMLHttpRequest();
        var url = "./kao.json";
        xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                myFunction(xmlhttp.responseText);
            }
        }
        xmlhttp.open("GET", url, true);
        xmlhttp.send();
        
        function myFunction(response) {
            var arr = JSON.parse(response);
        
            for(var i=0; i<arr.length; i++) {
                var latLng = new google.maps.LatLng(arr[i].Py,arr[i].Px);
                var marker = new google.maps.Marker({
                    position: latLng,  // 圖點位置
                    icon: {
                        path: google.maps.SymbolPath.CIRCLE,  // 使用圖圈圖形
                        strokeColor: "white", // 線條顏色
                        strokeWeight: 1,      // 線條粗細
                        fillColor: "red",     // 填充顏色
                        fillOpacity: 0.3,     // 填充透明度
                        scale: Math.floor((Math.random()*10)+1)  // 圖形大小
                    },
                    title: arr[i].Name,
                    map: map
                });
            }
        }
    }

    function showError(error) {
        var x = document.getElementById("demo");
        switch(error.code) {
            case error.PERMISSION_DENIED:
                x.innerHTML = "User denied the request for Geolocation."
                break;
            case error.POSITION_UNAVAILABLE:
                x.innerHTML = "Location information is unavailable."
                break;
            case error.TIMEOUT:
                x.innerHTML = "The request to get user location timed out."
                break;
            case error.UNKNOWN_ERROR:
                x.innerHTML = "An unknown error occurred."
                break;
        }
    }

    function getLocation() {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap';
        document.body.appendChild(script);
    }
    </script>
</head>

<body>
    <p id="demo">Google Maps JavaScript API Symbol 範例</p>
    <button onclick="getLocation()">顯示</button>
    <div id="mapholder"></div>
</body>
</html>

以自訂圖例呈現資料
除了用 google.maps.SymbolPath 提供的符號(symbol)呈現資料,Google 也提供了以自訂圖例呈現資料。只要載入圖例檔案的位置,並指定標記資料對應的圖例就可以了。
var iconBase = "https://maps.google.com/mapfiles/kml/shapes/";  // 圖例的來源位置
var marker = new google.maps.Marker({
   position: latLng,                       // 標記資料的經緯度
   icon: iconBase + "library_maps.png"});  // 標記資料對應的圖例
我們以《Google Maps JavaScript API 官方教學文件》所提供的 https://maps.google.com/mapfiles/kml/shapes/ 圖示為例,呈現高雄市觀光景點位置。同樣注意需申請您的 Google API 金鑰,以替代 YOUR_API_KEY。
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script>
    function initMap() {
        if (navigator.geolocation) {
            var options={timeout:10000};
            navigator.geolocation.getCurrentPosition(showPosition, showError, options);
        } else {
            var x = document.getElementById("demo");
            x.innerHTML = "Geolocation is not supported by this browser.";
        }
    }

    function showPosition(position) {
        lat = position.coords.latitude;
        lon = position.coords.longitude;
        latlon = new google.maps.LatLng(lat, lon)
        mapholder = document.getElementById("mapholder")
        mapholder.style.height = "500px";
        mapholder.style.width = "1100px";

        var myOptions = {
            center:latlon,zoom:16,
            mapTypeId:google.maps.MapTypeId.ROADMAP,
            mapTypeControl:false,
            navigationControlOptions:{style:google.maps.NavigationControlStyle.SMALL}
        }
        
        var map = new google.maps.Map(document.getElementById("mapholder"), myOptions);
        // Load json data from JSON file
        var xmlhttp = new XMLHttpRequest();
        var url = "./kao.json";
        xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                myFunction(xmlhttp.responseText);
            }
        }
        xmlhttp.open("GET", url, true);
        xmlhttp.send();
        
        function myFunction(response) {
            var arr = JSON.parse(response);
            var iconBase = "https://maps.google.com/mapfiles/kml/shapes/";  // 圖例的來源位置
        
            for(var i=0; i<arr.length; i++) {
                var latLng = new google.maps.LatLng(arr[i].Py,arr[i].Px);
                var marker = new google.maps.Marker({
                    position: latLng,                         // 標記資料的經緯度
                    icon: iconBase + "parking_lot_maps.png",  // 標記資料對應的圖例
                    title: arr[i].Name,
                    map: map
                });
            }
        }
    }

    function showError(error) {
        var x = document.getElementById("demo");
        switch(error.code) {
            case error.PERMISSION_DENIED:
                x.innerHTML = "User denied the request for Geolocation."
                break;
            case error.POSITION_UNAVAILABLE:
                x.innerHTML = "Location information is unavailable."
                break;
            case error.TIMEOUT:
                x.innerHTML = "The request to get user location timed out."
                break;
            case error.UNKNOWN_ERROR:
                x.innerHTML = "An unknown error occurred."
                break;
        }
    }

    function getLocation() {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap';
        document.body.appendChild(script);
    }
    </script>
</head>

<body>
    <p id="demo">Google Maps JavaScript API 使用自訂圖例範例</p>
    <button onclick="getLocation()">顯示</button>
    <div id="mapholder"></div>
</body>
</html>

將照片呈現在 Google Maps 上
既然可以使用自訂圖例,當然也就可以把照片直接呈現在 Google Maps 上囉,也是設定好照片來源位置和標記資料對應的照片就可以了:
var iconBase = "./img/";  // 照片的來源位置
var marker = new google.maps.Marker({
   position: latLng,                      // 標記資料的經緯度
   icon: iconBase + "yourPhoto"});        // 標記資料對應的照片

以熱度圖(Heat Map)呈現資料
熱度圖以色彩與圖形來呈現資料的分佈和強度。例如:密集或強度高的區域顯示紅色,強度低的區域則顯示綠色。氣象局常使用熱度圖來呈現降雨量,也可以使用在人口或事件發生的位置和頻率。
使用 Google Maps JavaScript API 呈現熱度圖有以下要項:
  • 載入 Google visualization 程式庫
  • 建立包含位置(經緯度)和權重(weight)的資料陣列
  • 建立熱度圖圖層 (HeatmapLayer)
熱度圖圖層是 google.maps.visualization 程式庫的一部分,預設不會載入。必須在 Maps JavaScript API 啟動程序網址中使用 libraries 參數載入它:
<script type="text/javascript" 
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=visualization">
</script>
製作熱度圖資料陣列 (heatmapData) 並建立 google.maps.visualization.HeatmapLayer 物件,呼叫 setMap() 方法將它新增到地圖。
var heatmap = new google.maps.visualization.HeatmapLayer({
  data: heatmapData});
heatmap.setMap(map);
以下為高雄市觀光景點位置JSON資料,呈現熱度圖的範例,因為在這個例子中沒有特別的數值內容,我們取 1~10 的亂數代表該筆資料的權重。注意需申請您的 Google API 金鑰,以替代 YOUR_API_KEY。
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script>
    function initMap() {
        if (navigator.geolocation) {
            var options={timeout:10000};
            navigator.geolocation.getCurrentPosition(showPosition, showError, options);
        } else {
            var x = document.getElementById("demo");
            x.innerHTML = "Geolocation is not supported by this browser.";
        }
    }

    function showPosition(position) {
        lat = position.coords.latitude;
        lon = position.coords.longitude;
        latlon = new google.maps.LatLng(lat, lon)
        mapholder = document.getElementById("mapholder")
        mapholder.style.height = "500px";
        mapholder.style.width = "1100px";

        var myOptions = {
            center:latlon,zoom:16,
            mapTypeId:google.maps.MapTypeId.TERRAIN,
            mapTypeControl:false,
            navigationControlOptions:{style:google.maps.NavigationControlStyle.SMALL}
        }
        
        var map = new google.maps.Map(document.getElementById("mapholder"), myOptions);
        // Load json data from JSON file
        var xmlhttp = new XMLHttpRequest();
        var url = "./kao.json";
        xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                myFunction(xmlhttp.responseText);
            }
        }
        xmlhttp.open("GET", url, true);
        xmlhttp.send();
        
        function myFunction(response) {
            var heatmapData=[];   // 建立heatmapData陣列存放資料
            var arr = JSON.parse(response);
        
            for(var i=0; i<arr.length; i++) {
                var latLng = new google.maps.LatLng(arr[i].Py,arr[i].Px);
                heatmapData.push({location: latLng, weight: Math.floor((Math.random()*10)+1)});
                // 把latLng push到heatmapData陣列中, weight:權重(亂數1~10)
            }
            var heatmap = new google.maps.visualization.HeatmapLayer({
                data: heatmapData,   // 放入heatmapData資料陣列
                dissipating: true,
                radius: 20,     // 每個點的半徑(單位px)
                opacity: 0.5,   // 熱圖圖層透明度(0~1)
                map: map        // 新增至地圖,相當於使用 heatmap.setMap(map);
            });
        }
    }

    function showError(error) {
        var x = document.getElementById("demo");
        switch(error.code) {
            case error.PERMISSION_DENIED:
                x.innerHTML = "User denied the request for Geolocation."
                break;
            case error.POSITION_UNAVAILABLE:
                x.innerHTML = "Location information is unavailable."
                break;
            case error.TIMEOUT:
                x.innerHTML = "The request to get user location timed out."
                break;
            case error.UNKNOWN_ERROR:
                x.innerHTML = "An unknown error occurred."
                break;
        }
    }

    function getLocation() {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=visualization&callback=initMap';
        document.body.appendChild(script);
    }
    </script>
</head>

<body>
    <p id="demo">Google Maps JavaScript API 熱度圖範例</p>
    <button onclick="getLocation()">顯示</button>
    <div id="mapholder"></div>
</body>
</html>

在 Google Maps 繪製形狀、折線、路線
還可以透過 Polyline 物件,將 path 屬性中放入點的經緯度座標在 Google Maps 上繪製形狀、折線、路線,Polyline 物件的屬性請參考《Google Maps JavaScript API Documentation - 形狀》:
var pathCoordinates=[];  // 路徑經緯度座標陣列
var flightPath = new google.maps.Polyline({  // 建立Polyline物件
    path: pathCoordinates,  // 放入座標陣列
    strokeColor:,        // 線條顏色
    strokeOpacity:,      // 線條透明度
    strokeWeight: });    // 線條寬度
flightPath.setMap(map);  //新增到地圖
完整的 Polyline 物件繪製折線範例,注意需申請您的 Google API 金鑰,以替代 YOUR_API_KEY:
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script>
    function initMap() {
        if (navigator.geolocation) {
            var options={timeout:10000};
            navigator.geolocation.getCurrentPosition(showPosition, showError, options);
        } else {
            var x = document.getElementById("demo");
            x.innerHTML = "Geolocation is not supported by this browser.";
        }
    }

    function showPosition(position) {
        var pathCoords = new Array();
        lat = position.coords.latitude;
        lon = position.coords.longitude;
        latlon = new google.maps.LatLng(lat, lon)
        mapholder = document.getElementById("mapholder")
        mapholder.style.height = "500px";
        mapholder.style.width = "1100px";

        var myOptions = {
            center:latlon,zoom:16,
            mapTypeId:google.maps.MapTypeId.ROADMAP,
            mapTypeControl:false,
            navigationControlOptions:{style:google.maps.NavigationControlStyle.SMALL}
        }
        
        var map = new google.maps.Map(document.getElementById("mapholder"), myOptions);
        // Load json data
        var xmlhttp = new XMLHttpRequest();
        var url = "./kao.json";
        xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                myFunction(xmlhttp.responseText);
            }
        }
        xmlhttp.open("GET", url, true);
        xmlhttp.send();
        
        function myFunction(response) {
            var arr = JSON.parse(response);
        
            for(var i=0; i<10; i++) {  // set arr.length = 5
                pathCoords.push(new google.maps.LatLng(arr[i].Py,arr[i].Px));
            }
            var runPath = new google.maps.Polyline({
                path: pathCoords,
                geodesic: true,
                strokeColor: "green",
                strokeOpacity: 0.7,
                strokeWeight: 2
            });
            runPath.setMap(map);
        }
    }

    function showError(error) {
        var x = document.getElementById("demo");
        switch(error.code) {
            case error.PERMISSION_DENIED:
                x.innerHTML = "User denied the request for Geolocation."
                break;
            case error.POSITION_UNAVAILABLE:
                x.innerHTML = "Location information is unavailable."
                break;
            case error.TIMEOUT:
                x.innerHTML = "The request to get user location timed out."
                break;
            case error.UNKNOWN_ERROR:
                x.innerHTML = "An unknown error occurred."
                break;
        }
    }

    function getLocation() {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap';
        document.body.appendChild(script);
    }
    </script>
</head>

<body>
    <p id="demo">Google Maps JavaScript API Polyline 折線繪製範例</p>
    <button onclick="getLocation()">顯示</button>
    <div id="mapholder"></div>
</body>
</html>

Google Maps 顯示街景圖
使用 StreetViewPanorama 物件可以建立街景圖,StreetViewPanorama 物件的屬性請參考《Google Maps JavaScript API Documentation - 街景服務》,簡單的使用範例,注意需申請您的 Google API 金鑰,以替代 YOUR_API_KEY:
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script>
    function initMap() {
        if (navigator.geolocation) {
            var options={timeout:10000};
            navigator.geolocation.getCurrentPosition(showPosition, showError, options);
        } else {
            var x = document.getElementById("demo");
            x.innerHTML = "Geolocation is not supported by this browser.";
        }
    }

    function showPosition(position) {
        lat = position.coords.latitude;
        lon = position.coords.longitude;
        latlon = new google.maps.LatLng(lat, lon)
        mapholder = document.getElementById("mapholder")

        var myOptions = {
            center:latlon,zoom:16
        }
        
        var map = new google.maps.Map(document.getElementById("mapholder"), myOptions);
        var marker = new google.maps.Marker({position:latlon,map:map,title:"現在位置"});
        var panorama = new google.maps.StreetViewPanorama(
            document.getElementById("pano"), {
              position: latlon,
              pov: {
                heading: 34,
                pitch: 10
              }
            });
        map.setStreetView(panorama);
    }

    function showError(error) {
        var x = document.getElementById("demo");
        switch(error.code) {
            case error.PERMISSION_DENIED:
                x.innerHTML = "User denied the request for Geolocation."
                break;
            case error.POSITION_UNAVAILABLE:
                x.innerHTML = "Location information is unavailable."
                break;
            case error.TIMEOUT:
                x.innerHTML = "The request to get user location timed out."
                break;
            case error.UNKNOWN_ERROR:
                x.innerHTML = "An unknown error occurred."
                break;
        }
    }

    function getLocation() {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap';
        document.body.appendChild(script);
    }
    </script>
    <style>
        html, body {
            height: 100%;
        }
        #mapholder, #pano {
            float: left;
            height: 95%;
            width: 45%;
        }
    </style>
</head>

<body>
    <p id="demo">Google Maps JavaScript API 顯示街景圖範例</p>
    <button onclick="getLocation()">取得位置</button>
    <div id="mapholder"></div>
    <div id="pano"></div>
</body>
</html>


參考資料 (References):
😺 Google Maps JavaScript API Documentation - 將資料視覺化
😺 Google Maps JavaScript API Documentation - 自訂圖例
😺 Google Maps JavaScript API Documentation - 熱度圖圖層