1. 程式人生 > >Angular 個人深究(五)【外部包引用 Leaflet 簡單實用】

Angular 個人深究(五)【外部包引用 Leaflet 簡單實用】

  Leaflet 使用
  
  最近在Angular專案中,用到了地圖,由於種種原因放棄了百度地圖api使用,最後選擇了leaflet,簡單介紹一下。
  
  介紹:
  
  Leaflet 是一個為移動裝置設計的互動式地圖的開源的 javascript庫, 並只有38k,包含了大多數開發者需要的地圖特點。
  
  準備:下載 leaflet 檔案
  
  訪問: Leaflet下載官網
  
  在單一的HTML頁面中使用Leaflet
  
  建立一個資料夾 leaflet_test
  
  資料夾下建立一個index.html
  
  將上述下載的leaflet檔案放到leaflet_test資料夾下
  
  在index.html插入如下程式碼
  
  <!-- 引入 檔案 -->
  
  <link rel="stylesheet" href="./leaflet.css" />
  
  <script src="./leaflet.js"> </script>
  
  <!-- 增加地圖高度 -->
  
  <style>
  
  #mapDiv { height: 300px; }
  
  </style>
  
  <!-- 建立一個 地圖的div id 必須有 但是自定義 -->
  
  <div id="mapDiv"></div>
  
  <script>
  
  //到 mapbox 官網註冊並建立下面的access token都是免費的,不過有5w次的瀏覽限制
  
  var url = 'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoia2FuZXdhbmciLCJhIjoiY2pwM2UxNHNkMGF1MzNwc2FtMnNhdXJsMCJ9.KZpCBtizDeltZO6JhGc6_w';
  
  //初始化 地圖
  
  var leafletMap = L.map('mapDiv').setView([41, 123], 5);
  
  //將圖層載入到地圖上,並設定最大的聚焦還有map樣式
  
  L.tileLayer(url, {
  
  maxZoom: 18,
  
  id: 'mapbox.streets'
  
  }).addTo(leafletMap);
  
  //增加一個marker ,地圖上的標記,並綁定了一個popup,預設開啟
  
  L.marker([41, 123]).addTo(leafletMap)
  
  .bindPopup("<b>Hello world!</b><br />I am a popup.").openPopup();
  
  //增加一個圈,設定圓心、半徑、樣式
  
  L.circle([41, 123], 500, {
  
  color: 'red',
  
  fillColor: '#f03',
  
  fillOpacity: 0.5
  
  }).addTo(leafletMap).bindPopup("I am a circle.");
  
  //增加多邊形
  
  L.polygon([
  
  [41, 123],
  
  [39, 121],
  
  [41, 126]
  
  ]).addTo(leafletMap).bindPopup("I am a polygon.");
  
  //為點選地圖的事件 增加popup
  
  var popup = L.popup();
  
  function onMapClick(e) {
  
  popup
  
  .setLatLng(e.latlng)
  
  .setContent("You clicked the map at " + e.latlng.toString())
  
  .openOn(leafletMap);
  
  }
  
  leafletMap.on('click', onMapClick);
  
  </script>
  
  上述程式碼可直接使用,下面先上效果圖,再解釋程式碼的含義
  
  程式碼解釋:
  
  1.引入Leaflet css 與js 檔案,官網要求,css在前 js在後。不過我簡單試過沒啥變化。
  
  2.增加 地圖css樣式,設定高度,這個官網要求必須的。不設定會不顯示地圖
  
  建立裝地圖的div 記住這個div的 id
  
  開始建立地圖,我們先去準備一個 瓦片圖層 本文使用的是 mapbox
  
  到 map box上註冊賬號,登入後 建立一個access token,copy到程式碼url accesstoken後面,使用我的也好使
  
  初始化map 使用 L.map('mapDiv').setView([51.505, -0.09], 13),其中[51.505, -0.09]地理位置,13是變焦的大小
  
  將圖層加到map上。其中url是圖層的資源的url,maxZoom 是最大的聚焦【mapbox官網最大的也是18了】,id 是 地圖的樣式並不是我們平常認識的id,本文選擇了 street 的map
  
  mapbox 支援的地圖樣式,共6個預設的(預設提供的,可以自己建立上傳)
  
  Mapbox Incidents V1 [id=mapbox.mapbox-incidents-v1]
  
  Mapbox Statellite[mapbox.satellite]
  
  ...
  
  加標記、加圓圈、加多邊形,再為地圖每個位置點選增加事件
  
  至此,簡單的應用就完成了。
  
  在單一頁面中使用中國各種地圖
  
  為什麼單獨說,因為leaflet提供了一個外掛 Leaflet.ChineseTmsProviders可以訪問 github主頁檢視。下面我們看看如何使用它。
  
  準備去github上下載外掛的js檔案 github下載,下載後同樣放到與leaflet包同一路徑下
  
  上一下外掛程式碼:
  
  L.TileLayer.ChinaProvider = L.TileLayer.extend({
  
  initialize: function(type, options) { // (type, Object)
  
  var providers = L.TileLayer.ChinaProvider.providers;
  
  var parts = type.split('.');
  
  var providerName = parts[0];
  
  var mapName = parts[1];
  
  var mapType = parts[2];
  
  var url = providers[providerName][mapName][mapType];
  
  options.subdomains =www.michenggw.com providers[providerName].Subdomains;
  
  L.TileLayer.prototype.initialize.call(this, url, options);
  
  }
  
  });
  
  L.TileLayer.ChinaProvider.providers = {
  
  TianDiTu: {
  
  Normal: {
  
  Map: "http://t{s}.tianditu.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}",
  
  Annotion: "http://t{s}.tianditu.cn/DataServer?T=cva_w&X={x}&Y={y}&L={z}"
  
  },
  
  Satellite: {
  
  Map: "http://t{s}.tianditu.cn/DataServer?T=img_w&X={x}&Y={y}&L={z}",
  
  Annotion: "http://t{s}.tianditu.cn/DataServer?T=cia_w&X={x}&Y={y}&L={z}"
  
  },
  
  Terrain: {
  
  Map: "http://t{s}.tianditu.cn/DataServer?T=ter_w&X={x}&Y={y}&L={z}",
  
  Annotion: "http://t{s}.tianditu.cn/DataServer?T=cta_w&X={x}&Y={y}&L={z}"
  
  },
  
  Subdomains: ['0', '1', '2', '3', '4', '5', '6', '7']
  
  },
  
  GaoDe: {
  
  Normal: {
  
  Map: 'http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
  
  },
  
  Satellite: {
  
  Map: 'http://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
  
  Annotion: 'http://www.yigouyule2.cn   webst0{s}.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}'
  
  },
  
  Subdomains: ["1", "2", "3", "4"]
  
  },
  
  Google: {
  
  Normal: {
  
  Map: "http://www.google.cn/maps/vt?lyrs=m

@189&gl=cn&x={x}&y={y}&z={z}"
  
  },
  
  Satellite: {
  
  Map: "http://www.google.cn/maps/vt?lyrs=s@189&gl=cn&x={x}&y={y}&z={z}"
  
  },
  
  Subdomains: [www.mhylpt.com]
  
  },
  
  Geoq: {
  
  Normal: {
  
  Map: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}",
  
  Color: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetColor/MapServer/tile/{z}/{y}/{x}",
  
  PurplishBlue: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
  
  Gray: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetGray/MapServer/tile/{z}/{y}/{x}",
  
  Warm: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetWarm/MapServer/tile/{z}/{y}/{x}",
  
  Cold: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetCold/MapServer/tile/{z}/{y}/{x}"
  
  },
  
  Subdomains: [www.feifanyule.cn/]
  
  }
  
  };
  
  L.tileLayer.chinaProvider = function(type, options) {
  
  return new L.TileLayer.ChinaProvider(type, options);
  
  };
  
  更改index.html檔案
  
  <script src="./leaflet.js"></script>
  
  <link rel="stylesheet" href="./leaflet.css" />
  
  <script src="leaflet.ChineseTmsProviders.js"></script>
  
  <style>
  
  //#mapDiv { height: 300px; }
  
  .test { height: 300px; }
  
  </style>
  
  <div id="mapDiv" class='test'></div>
  
  <script>
  
  //外掛把 定義了多個國內的瓦片圖層,我們只需要通過提供的方法訪問到相應的圖層即可
  
  //從外掛程式碼可以看出 需要傳入 providerName.mapName.mapType 從外掛程式碼中查詢所需要的值
  
  var test = L.tileLayer.chinaProvider('Geoq.Normal.Map', {
  
  maxZoom: 18,
  
  minZoom: 5
  
  });
  
  //此處可以定義多個圖層,並可以再頁面中進行選擇
  
  var baseLayers = {"測試地圖":test}
  
  var map = L.map("mapDiv", {
  
  center: [41.80, 123.43],
  
  zoom: 7,
  
  layers: [test],
  
  zoomControl: false
  
  });
  
  L.control.layers(baseLayers, null).addTo(map);
  
  L.control.zoom({
  
  zoomInTitle: '放大',
  
  zoomOutTitle: '縮小'
  
  }).addTo(map);
  
  </script>
  
  上結果圖,這次只是使用外掛沒有其他功能。中心點是瀋陽市。
  
  Leaflet 畫線裝飾外掛
  
  本次開發使用了另一個外掛polylineDecorator.js
  
  index.html
  
  //如下程式碼需要上一節的程式碼
  
  var arrow = L.polyline([[41.80, 123.43], [41.07, 123.00]], {opacity: 1,color: 'firebrick'}).bindPopup('I am red:').addTo(map);//
  
  var arrow2 = L.polyline([[41.80, 123.43], [40.13, 124.37]], {opacity: 1,color: 'lightgreen'}).bindPopup('I am green:').addTo(map);
  
  var arrow3 = L.polyline([[41.07, 123.00], [40.13, 124.37]], {opacity: 1,color: 'lightgreen'}).bindPopup('I am green:').addTo(map);
  
  var arrowHead = L.polylineDecorator(arrow, {
  
  patterns: [
  
  {offset: '30%' ,endOffset:'90%',repeat: 1000, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false,pathOptions: {stroke: true,weight:2,color: 'firebrick'}})}
  
  ]
  
  }).addTo(map);
  
  上圖:在一條線上增加了一個箭頭,還有很多的裝飾,可訪問github主頁檢視example 的程式碼
  
  在 angular中使用 leaflet.js
  
  由於leaflet是 javascript庫,而angular 使用的typescript 語言,這就存在一個問題。經過查詢,發現了ts的一個功能。.d.ts檔案的使用。
  
  注:如下內容,僅做介紹了,在我們的專案中是成功的引入了leaflet了,如果不好使,請大家自行查詢一下吧。推薦一個介紹文章 JavaScript 和 TypeScript 交叉口
  
  在專案的根目錄下建立檔案【angular框架中是 src下】 index.d.ts
  
  檔案內容:
  
  declare var L:any; //leaflet
  
  當然在angular.json需要引入相關的 leaflet的js檔案
  
  在projects->architect->build->options->scripts中加入leaflet.js的路徑
  
  相關的內容請查閱angular相關的介紹 Angular Cli Stories