uniapp實現地圖點聚合功能的詳細教程
任務
在工作中接到的一個任務,在app端實現如下功能:
- 地圖點聚合
- 地圖頁面支持tab切換(設備、勞務、人員)
- 支持人員搜索顯示分佈
但是uniapp原有的map標簽不支持點聚合功能(最新的版本支持瞭點聚合功能),所以采取瞭hybrid
原生html文件開發的方式
最新的版本map已支持,如下:
效果圖
h5的效果圖,與真機有點偏差
生成頁面
在pages.json
中定義distribution.vue
頁面
{ "path": "pages/distribution/distribution", "style": { "navigationBarTitleText": "人機分佈", "navigationBarTextStyle": "black" } },
頁面結構主要分為三個部分:頂部標題,tab切換,地圖畫佈
頂部標題
頂部標題就不用講瞭,一般打開微信小程序頁面或者app頁面,都是左—返回,中—標題,右—其他。存在默認設置,但這裡的話存在web-view(web 瀏覽器組件,可以用來承載網頁的容器),很有可能將頂部標題覆蓋掉,所以使用自定義標題,具體實現如下:
<view class="tab"> <!-- :isBack="true" --> <tab-left bgColor="bg-gradual-white" :isBack="true" :url="gobackurl"> <block slot="backText">返回</block> <block slot="content">人機分佈</block> </tab-left> </view>
tab切換
主要實現設備/勞務/人員的tab切換,固定在app內容頂部,難點在於tab切換時,需要實現頁面和html頁面通信,改變地圖內容,主要需要做以下幾個功能:
- 調用接口(getNavInfo)獲取maplists信息
// 獲取導航欄數值 getNav(){ let params={ ProjectId:this.projectId, OrgCode:this.orgcode } Api.getNavInfo(params).then(res=>{ console.log('嘻嘻',res) if(res.data.length>0){ res.data.forEach((item,index)=>{ this.maplists[index].number=item }) }else{ uni.showToast({ title:'獲取導航欄數值失敗', icon:'none' }) } }) },
- 切換tab時,實現與頁面和html的通信
swichNav(item) { // this.reportisChoose = parseInt(e.currentTarget.id - 1); // this.url += encodeURIComponent(JSON.stringify([{'s':1111}])); item.check=!item.check if(item.check){ this.maker.push(item.id) }else{ let index=0 this.maker.forEach((x,i)=>{ if(x===item.id){ index=i } }) this.maker.splice(index,1) } console.log('this.makerxxx',this.maker) this.url ='../../hybrid/html/map.html?'+ "access_token="+this.token+"&maker="+JSON.stringify(this.maker)+"&baseUrl="+this.baseUrl+"&projectId=" + this.projectId+"&OrgCode="+this.orgcode },
地圖畫佈
地圖畫佈主要是嵌入map.html
,這裡主要是用到瞭web-view
,需要註意以下兩個地方:
web-view
:一般是占滿全屏的,優先級最高,所以會覆蓋tab部分,故要設定高度或者top值,
主要實現如下:
// 獲取設備信息 getEqData() { let _this=this console.log('進來來'); let projectId = this.$store.state.user.projectId; Api.getEqlocation(projectId).then(res => { if (res.data.success) { this.eqData = res.data.data; console.log('結果是', this.eqData); this.eqData.forEach(item=>{ item['x']=this.longitude+Math.random(0,1000) item['y']=this.latitude+Math.random(0,1000) item['text']='設備信息' item['path']='../../static/01.png' }) } }) }, // 獲取屏幕高度 getwh() { const { windowWidth, windowHeight } = uni.getSystemInfoSync(); console.log('windowWidth, windowHeight', windowWidth, windowHeight); this.height = windowHeight; this.width = windowWidth; let _this = this; this.$nextTick(function() { this.computeHeight(); this.setWebHeight() }); }, // 設置web-view樣式 setWebHeight(){ let _this=this console.log('height',this.$scope) // #ifdef APP-PLUS var currentWebview = this.$scope.$getAppWebview(); //獲取當前web-view setTimeout(function(){ var wv = currentWebview.children()[0]; console.log('wv',wv); wv.setStyle({ //設置web-view距離頂部的距離以及自己的高度,單位為px top: _this.top, height: _this.height, // 雙指縮放 scalable:true }); },1000) // #endif }, // 計算導航欄和頂部高度 computeHeight() { let _this = this; let info = uni.createSelectorQuery().select('.map-top-tab'); info.boundingClientRect(function(data) { console.log('計算出來什麼高度', data); _this.top = data.height; }).exec(); let info2=uni.createSelectorQuery().select('.tab') info2.boundingClientRect(function(data) { console.log('計算出來什麼高度222', data); _this.top += data.height; _this.height = _this.height-_this.top; }).exec(); console.log('sssssssssssssssss',this.height,this.top) }
- web-view嵌入本地網頁,主要放在
../../hybrid/html
文件下,這個官網給出瞭建議和結構圖,如下:
┌─components
├─hybrid
│ └─html
│ ├─css
│ │ └─test.css
│ ├─img
│ │ └─icon.png
│ ├─js
│ │ └─test.js
│ └─local.html
├─pages
│ └─index
│ └─index.vue
├─static
├─main.js
├─App.vue
├─manifest.json
└─pages.json
map.html頁面設置
雖然是個html頁面,但主要是實現地圖點聚合(主要使用百度地圖api實現) 的功能,所以主要要引入以下幾個依賴:
<link rel="stylesheet" href="https//api.map.baidu.com/library/SearchInfoWindow/1.5/src/SearchInfoWindow_min.css" rel="external nofollow" /> <script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=Ps5KaIdB9sSNUbDwECgTtBL7xluVv91s"></script> <script src="//libs.baidu.com/jquery/1.9.0/jquery.js"></script> <script type="text/javascript" src="https://api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay_min.js"></script> <script type="text/javascript" src="js/MakerClusterer.js"></script> <script src="js/vue.min.js"></script> <script src="js/axios.js"></script>
實現頁面通信,分解url參數
created() { axios.defaults.headers.post['Content-Type'] = 'application/json'; let _this = this this.baseUrl = this.getQueryString('baseUrl') this.projectId = this.getQueryString('projectId'); this.access_token_app = this.getQueryString('access_token'); this.OrgCode = this.getQueryString('OrgCode') // console.log('傳過來的數據', this.baseUrl, this.projectId, this.access_token_app, this.OrgCode) localStorage.setItem('baseUrl', this.baseUrl) localStorage.setItem('access_token_app', this.access_token_app) axios.defaults.headers.common['Authorization'] = "Bearer " + localStorage.getItem('access_token_app') this.maker = this.getQueryString('maker') // console.log('this.maker111', this.maker) this.maker = JSON.parse(this.maker) // console.log('this.maker', this.maker) if (this.maker !== null) { // 1--設備,2--勞務,3--人員 this.maker.forEach(y => { // 1--設備,2--勞務,3--人員 switch (y) { case 1: console.log('進入設備區域瞭') _this.getEqData() break case 2: console.log('進入勞務區域瞭') _this.getServiceData() break case 3: console.log('進入人員區域瞭') _this.getUserData() break } }) } this.$nextTick(function() { _this.initMap() }) }, mounted() { document.addEventListener('UniAppJSBridgeReady', function() { uni.getEnv(function(res) { console.log('當前環境:' + JSON.stringify(res)); }); }); }, methods:{ //取url中的參數值 getQueryString(name) { // 正則:[找尋'&' + 'url參數名字' = '值' + '&']('&'可以不存在) var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i'); let r = window.location.search.substr(1).match(reg); if (r != null) { // 對參數值進行解碼 return r[2] } return null; }, }
初始化地圖
// 初始化地圖 initMap() { // 百度地圖API功能 this.map = new BMap.Map("allmap"); // 初始化地圖,創建中心坐標和地圖實例 this.map.centerAndZoom(new BMap.Point(116.331398, 39.897445), 10); // this.map.addEventListener("tilesloaded",function(){alert("地圖加載完畢");}) // 啟用拖拽 // this.map.enableInertialDragging() // this.map.enableScrollWheelZoom(); // 啟用雙指縮放 // this.map.enablePinchToZoom() // this.map.addControl(new BMap.NavigationControl()); this.map.addControl(new BMap.ScaleControl()); this.map.addControl(new BMap.OverviewMapControl()); let temMap = this.map // 添加帶有定位的導航控件,放大,縮小 var navigationControl = new BMap.NavigationControl({ // 靠左上角位置 anchor: BMAP_ANCHOR_TOP_RIGHT, // 偏移值 offset: new BMap.Size(5, 50), // LARGE類型 type: BMAP_NAVIGATION_CONTROL_LARGE, // 是否顯示級別 showZoomInfo: true, // 啟用顯示定位 enableGeolocation: true }); this.map.addControl(navigationControl); // 添加定位控件 var geolocationControl = new BMap.GeolocationControl(); geolocationControl.addEventListener("locationSuccess", function(e) { // 定位成功事件 var address = ''; address += e.addressComponent.province; address += e.addressComponent.city; address += e.addressComponent.district; address += e.addressComponent.street; address += e.addressComponent.streetNumber; }); geolocationControl.addEventListener("locationError", function(e) { // 定位失敗事件 alert(e.message); }); this.map.addControl(geolocationControl); },
點聚合功能實現
主要起作用的是MarkerClusterer
類
watch: { markerArr(val) { if (val != null) { console.log('ccccc', val) if (this.markerClusterer) { this.markerClusterer.clearMarkers() } this.markerClusterer = new BMapLib.MarkerClusterer(this.map, { markers: val }); // 所有標記顯示在地圖內 this.map.setViewport(this.pointArray) console.log('當前地圖級別', this.map.getZoom()) } }, }
搜索功能實現
// 根據名稱搜索項目 searchByName() { console.log('運動少殺殺殺', this.arrAll) let markerByName = this.arrAll.filter(item => item.name.indexOf(this.keyword) !== -1) console.log('過濾後的照片', markerByName) if (markerByName.length === 0) { alert('搜索內容無定位信息,請重新搜索') this.keyword = '' return } // 設置最大級別數 // this.map.setMaxZoom(10) this.markerArr = [] this.createDefineMarker(markerByName) this.map.setViewport(this.pointArray) console.log('當前地圖級別', this.map.getZoom()) },
總結
到此這篇關於uniapp實現地圖點聚合功能的文章就介紹到這瞭,更多相關uniapp地圖點聚合功能內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- js前端獲取用戶位置及ip屬地信息
- 利用JavaScript獲取用戶IP屬地方法詳解
- uniapp和vue的區別詳解
- JavaScript接入百度地圖API的方法步驟
- vue+elementUi實現點擊地圖自動填充經緯度以及地點