UNPKG

iovmap

Version:
333 lines (327 loc) 10.1 kB
/* * Copyright (C) 2017 dehai.site All Rights Reserved. * * @author level <dehai168@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 'use strict' // 第三方集群插件(https://github.com/Leaflet/Leaflet.markercluster) import markerCluster from 'leaflet.markercluster' import 'leaflet.markercluster/dist/MarkerCluster.css' import 'leaflet.markercluster/dist/MarkerCluster.Default.css' //离线 import offline from '../assets/default/0.png' //在线行驶 import online from '../assets/default/1.png' //告警 import alarm from '../assets/default/2.png' //不定位 import noposition from '../assets/default/3.png' //停车 import stop from '../assets/default/4.png' import m0 from '../assets/m0.png' import m1 from '../assets/m1.png' import m2 from '../assets/m2.png' import m3 from '../assets/m3.png' import m4 from '../assets/m4.png' export class MarkerList_Native { constructor(map, cb, cb2) { this.map = map this.clickCB = cb this.closeCB = cb2 this.list = [] //数据列表 this.markers = null this.markersSubArray = [] this.imgList = [[offline, online, alarm, noposition, stop]] //车辆图像列表 this.popup = null //气泡 this.popupId = null //气泡id } /** * 增加 markerList * @param {Array} listArray */ push(listArray) { if (listArray.length > 0) { this.list = listArray this._drawCluster() } else { this._clear() } } _drawCluster() { const that = this if (!this.markers) { this.markers = L.markerClusterGroup({ showCoverageOnHover: false, //当您将鼠标悬停在集群上时,它会显示其标记的边界 removeOutsideVisibleBounds: true, //从地图中移除离视口太远的集群和标记以提高性能 spiderfyOnMaxZoom: false, //当您单击一个标记时,它会将所有其他标记都“蜘蛛网化”,并将它们放在一个单独的组中 disableClusteringAtZoom: this.map.getMaxZoom() - 2, //在最大缩放级别之前不进行群集 iconCreateFunction: function (cluster) { //集群绘制 const size = cluster.getChildCount() let style = 'text-align:center;' if (size <= 500) { style += 'margin-top:-26px;margin-left:-26px;width:53px;height:52px;line-height:52px;background:url(' + m0 + ') no-repeat;' } else if (size <= 1000) { style += 'margin-top:-27px;margin-left:-28px;width:56px;height:55px;line-height:55px;background:url(' + m1 + ') no-repeat;' } else if (size <= 2000) { style += 'margin-top:-32px;margin-left:-33px;width:66px;height:65px;line-height:65px;background:url(' + m2 + ') no-repeat;' } else if (size <= 4000) { style += 'margin-top:-38px;margin-left:-39px;width:78px;height:77px;line-height:77px;background:url(' + m3 + ') no-repeat;' } else { style += 'margin-top:-44px;margin-left:-45px;width:90px;height:89px;line-height:89px;background:url(' + m4 + ') no-repeat;' } //绘制图标 const myIcon = L.divIcon({ className: 'myIconClass', html: "<div style='" + style + "'>" + size + '</div>', }) return myIcon }, }) for (let index = 0; index < this.list.length; index++) { const item = this.list[index] const myIcon = this._getIcon(item) const marker = L.marker([item.lat, item.lng], { icon: myIcon, alt: item.id, //唯一标记 }) this.markers.addLayer(marker) this.markersSubArray.push(marker) } this.markers.on('click', function (a) { if (that.clickCB) { that.clickCB(a.sourceTarget.options.alt) } }) this.map.addLayer(this.markers) } else { for (let index = 0; index < this.list.length; index++) { const item = this.list[index] const myIcon = this._getIcon(item) const marker = L.marker([item.lat, item.lng], { icon: myIcon, alt: item.id, //唯一标记 }) let isHad = false for (let index = 0; index < this.markersSubArray.length; index++) { const marker = this.markersSubArray[index] if (marker.options.alt === item.id) { this.markersSubArray[index].setIcon(myIcon) this.markersSubArray[index].setLatLng([item.lat, item.lng]) isHad = true break } } if (!isHad) { this.markers.addLayer(marker) this.markersSubArray.push(marker) } } this.markers.refreshClusters(this.markersSubArray) } } /** * 清理 markerList */ remove() { this._clear() } /** * 打开一个气泡 * @param {*} id */ openPopup(id) { const currentZoom = this.map.getZoom() if (currentZoom !== this.maxZoom) { this.map.setZoom(this.maxZoom) } const index = this.list.findIndex((v) => { return v.id === id }) if (index > -1) { const object = this.list[index] if (this.popup) { this._movePopup([object.lat, object.lng], true) } else { this.popup = this._createPopup([object.lat, object.lng]) } this.popupId = id } } /** * 移动已存在的popup * @param {*} latlng */ _movePopup(latlng, isOpen) { if (this.popup) { this.popup.setLatLng(latlng) if (isOpen) { this.map.openPopup(this.popup) } } } /** * 创建popup * @param {*} latlng * @param {*} content * @returns */ _createPopup(latlng, content) { let popup = L.popup({ className: 'myIconClass', autoPan: false, offset: [0, -16], maxWidth: 600, }) .setLatLng(latlng) .setContent(content || 'loading...') .openOn(this.map) const that = this this.map.on('popupclose', function (e) { if (that.closeCB) { that.closeCB() } }) return popup } /** * 清理popup */ _clearPopup() { if (this.popup) { this.popup.remove() this.map.off('popupclose') this.popup = null this.popupId = null } } /** * 关闭气泡 */ closePopup() { if (this.popup) { this.popup.close() } } /** * 设定气泡内容 * @param {*} htmlStr */ setPopupContent(htmlStr) { if (this.popup) { this.popup.setContent(htmlStr) } } /** * 设定图片地址 * @param {*} array */ setImageSrc(array) { this.imgList = [].concat(array) } /** * 清理 */ _clear() { if (this.markers) { this.markers.clearLayers() this.markers = null } this.markersSubArray.length = 0 } /** * 获取元素图标 * @param {*} one */ _getIcon(one) { let type = parseInt(one.type ? one.type : 0) let state = parseInt(one.state ? one.state : 0) let direction = parseInt(one.direction ? one.direction : 0) // 方向 let img = one.img || this.imgList[type][state] let imgSize = this._getRotatedDimensions( { offsetWidth: one.imgWidth || 32, offsetHeight: one.imgHeight || 32 }, direction, ) const textWidth = this._getTextWidth(one.text) let width = textWidth > 32 ? textWidth : 32 let height = 18 + imgSize.newHeight let style = 'transform:rotate(' + direction + 'deg);max-width:32px;max-height:32px;' if (one.imgWidth && one.imgHeight) { style += 'width:' + one.imgWidth + 'px;height:' + one.imgHeight + 'px;' } //绘制图标 let myIcon = L.divIcon({ className: 'myIconClass', iconSize: [width, height], html: "<div align='center' style='height:" + height + 'px;width:' + width + "px'><span style='display:block;width:100%;background-color:#fff;font-size:12px'>" + one.text + "</span><img style='" + style + "' src=" + img + '></img></div>', }) return myIcon } /** * 获取旋转后的尺寸 * @param {*} element * @param {*} angle * @returns */ _getRotatedDimensions(element, angle) { const originalWidth = element.offsetWidth const originalHeight = element.offsetHeight // 将角度转换为弧度 const radianAngle = (angle * Math.PI) / 180 // 计算旋转后的宽度和高度 const newWidth = Math.abs(originalWidth * Math.cos(radianAngle)) + Math.abs(originalHeight * Math.sin(radianAngle)) const newHeight = Math.abs(originalWidth * Math.sin(radianAngle)) + Math.abs(originalHeight * Math.cos(radianAngle)) return { newWidth, newHeight } } /** * 获取文字宽度 * @param {*} text * @param {*} font * @returns */ _getTextWidth(text, font = '12px Arial') { const canvas = document.createElement('canvas') const context = canvas.getContext('2d') context.font = font const textMetrics = context.measureText(text) return textMetrics.width } }