/**
* 二次封装地图对象
*/
import * as maptalks from "./libs/maptalks"
import Tool from './ext/tool/index'
import Geom from './ext/geom/index'
import * as layers from './ext/layer'
import EasyDrawTool from './ext/draw/EasyDrawTool'
import * as controls from './ext/control'
import InfoWindow from './ext/InfoWindow'
import 'xgplayer'
import FlvJsPlayer from 'htxgplayer-flv.js'
class EasyMap {
/**
* EasyMap地图类
* @constructor
* @param {String} container - DOM元素id
* @param {Object} options - 配置项
* @param {EasyTileLayer} options.defaultLayer - 默认基础图层
* @param {Array} options.center - 地图中心位置,默认为 [114.515013, 38.041251]
* @param {Array} options.extent - 地图范围
* @param {Boolean} options.zoom - 地图初始缩放级别,默认为7
* @param {Boolean} options.seamlessZoom - 是否使用无缝缩放模式,默认为false
* @param {number|undefined} options.minZoom - 地图最小缩放级别
* @param {number|undefined} options.maxZoom - 地图最大缩放级别
* @param {boolean|undefined} options.zoomControl - 是否显示地图缩放控件,默认为 false
* @param {boolean|undefined} options.scaleControl - 是否显示比例尺控件,默认为 false
* @param {boolean|undefined} options.overviewControl - 是否显示鹰眼控件,默认为 false
*/
constructor(container, options = {}) {
this.curIndex = 0
this.map = null
// 默认图层
this._layers = [new layers.EasyVectorLayer('default_vector')]
// 基础图层
if (options.defaultLayer !== undefined) {
this._baseLayer = options.defaultLayer
} else {
this._baseLayer = new layers.EasyTileLayer('base', {
urlTemplate: 'http://webrd{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
subdomains: ['01', '02', '03', '04']
})
}
this.container = container
// 默认配置对象
const defaultOption = {
center: [114.515013, 38.041251], // 石家庄
zoom: 7,
layers: [this._layers[0].layer],
seamlessZoom: false,
zoomControl: false,
scaleControl: false,
overviewControl: false,
baseLayer: this._baseLayer.layer,
attribution: false
};
//合并配置
let option = {}
Object.assign(option, defaultOption, options)
this._initMap(option)
}
/**
* 初始化地图
* @param {Object} option - 地图初始化配置项
*/
_initMap(option) {
this.map = new maptalks.Map(this.container, option)
this._baseLayer.map = this
this._layers.forEach(e => {
e.map = this
})
}
/**
* 获取空间参考
* @returns {*} 空间参考
*/
getSpatialReference() {
return this.map.getSpatialReference()
}
/**
* 设置空间参考
* @param {Object} spatialReference 要设置的空间参考
* @returns {EasyMap}
*/
setSpatialReference(spatialReference) {
this.map.setSpatialReference(spatialReference)
return this
}
/**
* 获取地图的当前缩放等级
* @return Integer 缩放等级
*/
getZoom() {
return this.map.getZoom()
}
/**
* 设置地图的缩放等级
* @param zoom
* @param options
* @return {EasyMap}
*/
setZoom(zoom, options = void 0) {
this.map.setZoom(zoom, options)
return this
}
/**
* 放大地图,缩放等级+1
* @return {EasyMap}
*/
zoomIn() {
this.map.zoomIn()
return this
}
/**
* 缩小地图,缩放等级-1
* @return {EasyMap}
*/
zoomOut() {
this.map.zoomOut()
return this
}
/**
* 获取地图的中心点
* @param {String} type 返回的坐标类型,默认为Number数组
* @returns {maptalks.Coordinate|Array<Number>} 坐标点
*/
getCenter(type = null) {
const coordinate = this.map.getCenter()
if (type === 'coordinate') {
return coordinate
} else {
return maptalks.Coordinate.toNumberArrays(coordinate).map(n => n.toFixed(6))
}
}
/**
* 设置地图的中心点
* @param center Coordinate 中心点
* @return {EasyMap}
*/
setCenter(center) {
this.map.setCenter(center)
return this
}
/**
* 获取地图的最大范围
* @return Extent 范围,[xmin,ymin,xmax,ymax]
*/
getMaxExtent() {
return this.map.getMaxExtent()
}
/**
* 设置地图的最大范围
* @param extent Extent 范围,[xmin,ymin,xmax,ymax]
* @return {EasyMap}
*/
setMaxExtent(extent) {
this.map.setMaxExtent(extent)
return this
}
/**
* 添加图层
* @param {EasyLayer} layer 要添加的图层
* @return {EasyMap}
*/
addLayer(layer) {
this.map.addLayer(layer.layer)
this._layers.push(layer)
return this
}
/**
* 根据图层id获取图层
* @param id String 图层id
* @return {EasyLayer|undefined} 获取到的图层
*/
getLayer(id) {
let layer = undefined
this._layers.forEach(e => {
if (e.id === id) {
layer = e
}
})
return layer
}
/**
* 获取基础图层
* @returns {*}
*/
getBaseLayer() {
return this._baseLayer
}
/**
* 获取所有图层
* @returns {[EasyLayer]} 获取到的图层
*/
getLayers(filter = null) {
if (filter === null) {
filter = function() {
return true
}
}
const layers = []
this._layers.forEach(e => {
if (filter(e)) {
layers.push(e)
}
})
return layers
}
/**
* 移除指定图层
* @param {EasyLayer} layer
* @return {EasyMap}
*/
removeLayer(layer) {
this.map.removeLayer(layer.layer)
this._layers.splice(this._layers.findIndex(e => e.id === layer.id), 1)
return this
}
/**
* 事件绑定
* @param {String} eventsOn 要注册的事件类型
* @param {*} handler 要调用的处理函数
* @param {*} context 处理程序的上下文
*/
on(eventsOn, handler, context = null) {
this.map.on(eventsOn, handler, context)
}
/**
* 事件绑定,别名
* @param {String} eventsOn 要注册的事件类型
* @param {*} handler 要调用的处理函数
* @param {*} context 处理程序的上下文
*/
addMapEventListener(eventsOn, handler, context = null) {
this.map.addEventListener(eventsOn, handler, context)
}
/**
* 单次事件绑定,调用一次后移除
* @param {String} eventTypes 要注册的事件类型
* @param {*} handler 要调用的处理函数
* @param {*} context 处理程序的上下文
*/
once(eventTypes, handler, context = null) {
this.map.once(eventTypes, handler, context)
}
/**
* 单次事件绑定,调用一次后移除,别名
* @param {String} eventTypes 要注册的事件类型
* @param {*} handler 要调用的处理函数
* @param {*} context 处理程序的上下文
*/
addMapEventListenerOnce(eventTypes, handler, context = null) {
this.map.once(eventTypes, handler, context)
}
/**
* 事件移除
* @param {String} eventsOff 要移除的事件类型
* @param {*} handler 要调用的处理函数
* @param {*} context 处理程序的上下文
*/
un(eventsOff, handler, context = null) {
this.map.off(eventsOff, handler, context)
}
/**
* 事件移除,别名
* @param {String} eventsOff 要移除的事件类型
* @param {*} handler 要调用的处理函数
* @param {*} context 处理程序的上下文
*/
removeMapEventListener(eventsOff, handler, context = null) {
this.map.removeEventListener(eventsOff, handler, context)
}
/**
* 触发事件
* @param eventType 要触发的事件类型
* @param param 传给handler的参数
*/
fire(eventType, param) {
this.map.fire(eventType, param)
}
/**
*清空指定图层上的内容,如果不传递图层id则清空所有图层上的内容
* @param id 图层id
*/
clean(id) {
if (!id) {
let layers = this.map.getLayers()
for (let i = 0; i < layers.length; i++) {
layers[i].clear()
}
}else{
let layer = this.map.getLayer(id)
if (layer){
layer.clear()
}
}
}
/**
* 测距
*/
measureLine() {
let distanceTool = new maptalks.DistanceTool({
'symbol': {
'lineColor': '#34495e',
'lineWidth': 2
},
'vertexSymbol': {
'markerType': 'ellipse',
'markerFill': '#1bbc9b',
'markerLineColor': '#000',
'markerLineWidth': 3,
'markerWidth': 10,
'markerHeight': 10
},
'labelOptions': {
'textSymbol': {
'textFaceName': 'monospace',
'textFill': '#fff',
'textLineSpacing': 1,
'textHorizontalAlignment': 'right',
'textDx': 15,
'markerLineColor': '#b4b3b3',
'markerFill': '#000'
},
'boxStyle': {
'padding': [6, 2],
'symbol': {
'markerType': 'square',
'markerFill': '#000',
'markerFillOpacity': 0.9,
'markerLineColor': '#b4b3b3'
}
}
},
'clearButtonSymbol': [{
'markerType': 'square',
'markerFill': '#000',
'markerLineColor': '#b4b3b3',
'markerLineWidth': 2,
'markerWidth': 15,
'markerHeight': 15,
'markerDx': 20
}, {
'markerType': 'x',
'markerWidth': 10,
'markerHeight': 10,
'markerLineColor': '#fff',
'markerDx': 20
}],
'language': 'zh-CN'
}).addTo(this.map);
}
/**
* 测面积
*/
measureArea(func) {
let areaTool = new maptalks.AreaTool({
'symbol': {
'lineColor': '#1bbc9b',
'lineWidth': 2,
'polygonFill': '#fff',
'polygonOpacity': 0.3
},
'vertexSymbol': {
'markerType': 'ellipse',
'markerFill': '#34495e',
'markerLineColor': '#1bbc9b',
'markerLineWidth': 3,
'markerWidth': 10,
'markerHeight': 10
},
'labelOptions': {
'textSymbol': {
'textFaceName': 'monospace',
'textFill': '#fff',
'textLineSpacing': 1,
'textHorizontalAlignment': 'right',
'textDx': 15
},
'boxStyle': {
'padding': [6, 2],
'symbol': {
'markerType': 'square',
'markerFill': '#000',
'markerFillOpacity': 0.9,
'markerLineColor': '#b4b3b3'
}
}
},
'clearButtonSymbol': [{
'markerType': 'square',
'markerFill': '#000',
'markerLineColor': '#b4b3b3',
'markerLineWidth': 2,
'markerWidth': 15,
'markerHeight': 15,
'markerDx': 22
}, {
'markerType': 'x',
'markerWidth': 10,
'markerHeight': 10,
'markerLineColor': '#fff',
'markerDx': 22
}],
language: 'zh-CN'
}).addTo(this.map);
func(areaTool.getLastMeasure())
}
/**
* 获取两个坐标点间的距离
* @param {Array} coord1 坐标点1
* @param {Array} coord2 坐标点2
* @returns {null|number} 距离/单位:米
*/
getLength(coord1, coord2) {
return this.map.computeLength(coord1, coord2)
}
/**
* 获取地理区域的面积
* @param {Array} coords 区域坐标数组
* @returns {null|number} 面积/单位:平方米
*/
getArea(coords) {
return new maptalks.Polygon([coords]).getArea()
}
/**
* 所有交互启动/停止
* @param{boolean} onOrOff true:启动交互 false:禁用交互
* @param{String} type 交互类型:draggable,zoomable,scrollWheelZoom,touchZoom,doubleClickZoom
*/
interaction(onOrOff,type) {
if (!type){
this.map.config('draggable', onOrOff);
this.map.config('zoomable', onOrOff);
this.map.config('scrollWheelZoom', onOrOff);
this.map.config('touchZoom', onOrOff);
this.map.config('doubleClickZoom', onOrOff);
}else{
this.map.config(type, onOrOff);
}
}
/**
* 显示图层控件
*/
showMapControl(){
this.showZoomControl()
this.showScaleControl()
this.showOverviewControl()
}
/**
* 隐藏图层控件
*/
hideMapControl(){
this.closeZoomControl()
this.closeScaleControl()
this.closeOverviewControl()
}
/**
* 显示缩放控件
*/
showZoomControl() {
if (this.map.zoomControl){
if(!this.map.zoomControl.isVisible()){
this.map.zoomControl.show()
}
}else{
let zoom = new maptalks.control.Zoom({
'position' : 'top-left',
'slider' : true,
'zoomLevel' : true
});
zoom.addTo(this.map)
this.map.zoomControl = zoom
}
}
/**
* 关闭缩放控件
*/
closeZoomControl() {
if (this.map.zoomControl){
this.map.zoomControl.hide()
}
}
/**
* 设置缩放控件
* @param{Object} options
*/
setZoomControl(options) {
console.log(this.map);
if (options){
if (this.map.zoomControl){
let option = {}
let defaultOption = this.map.zoomControl.options
Object.assign(option, defaultOption, options);
this.map.zoomControl.remove()//?必须先移除原来的控件,再设置,否则'position'属性不起作用
let zoom = new maptalks.control.Zoom(option);
zoom.addTo(this.map)
this.map.zoomControl = zoom
}
}
}
/**
* 显示比例尺控件
*/
showScaleControl() {
if (this.map.scaleControl){
if(!this.map.scaleControl.isVisible()){
this.map.scaleControl.show()
}
}else{
let metric = new maptalks.control.Scale({
'position' : 'bottom-left',
'maxWidth': 150,
'metric': true,
'imperial': false
});
metric.addTo(this.map)
this.map.scaleControl = metric
}
}
/**
* 关闭比例尺控件
*/
closeScaleControl() {
if (this.map.scaleControl){
this.map.scaleControl.hide()
}
}
/**
* 设置比例尺控件
*/
setScaleControl(options) {
if (options){
if (this.map.scaleControl){
let option = {}
let defaultOption = this.map.scaleControl.options
Object.assign(option, defaultOption, options);
this.map.scaleControl.remove()//?必须先移除原来的控件,再设置,否则'position'属性不起作用
let metric = new maptalks.control.Scale(option);
metric.addTo(this.map)
this.map.scaleControl = metric
}
}
}
/**
* 显示鹰眼控件
*/
showOverviewControl() {
// this.map.overviewControl.show()
if (this.map.overviewControl){
if(!this.map.overviewControl.isVisible()){
this.map.overviewControl.show()
}
}else{
let overview = new maptalks.control.Overview();
overview.addTo(this.map)
this.map.overviewControl = overview
}
}
/**
* 关闭鹰眼控件
*/
closeOverviewControl() {
if (this.map.overviewControl){
this.map.overviewControl.hide()
}
}
/**
* 设置鹰眼控件
*/
setOverviewControl(options) {
if (options){
if (this.map.overviewControl){
let option = {}
let defaultOption = this.map.overviewControl.options
Object.assign(option, defaultOption, options);
this.map.overviewControl.remove()//?必须先移除原来的控件,再设置,否则'position'属性不起作用
let overview = new maptalks.control.Overview(option);
overview.addTo(this.map)
this.map.overviewControl = overview
}
}
}
/**
* 创建热力图层
* @param{String} id 图层id
* @param{Array} data
* @param{Object} options
* @returns {EasyHeatmapLayer} 热力图层
*/
createHeatMap(id,data,options){
let heatmapLayer = new layers.EasyHeatmapLayer(id,data,options)
heatmapLayer.addTo(this)
return heatmapLayer
}
/**
* 创建聚合图层
* @param{String} id
* @param{Array} data
* @param{Object} options
* @returns {EasyClusterLayer} 聚合图层
*/
createClusterLayer(id,data,options){
let clusterLayer = new layers.EasyClusterLayer(id,data,options)
clusterLayer.addTo(this)
return clusterLayer
}
/**
* 显示百度地图
*/
setBdBaseLayer(){
this.map.removeLayer('skymarker')
this.map.setBaseLayer(new maptalks.TileLayer("base",{
urlTemplate:'http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1',
subdomains:[0,1,2,3,4,5,6,7,8,9],
}))
this.map.config("spatialReference",{ projection : 'baidu' })
}
/**
* 显示高德地图
*/
setGdBaseLayer(){
this.map.removeLayer('skymarker')
this.map.setBaseLayer(new maptalks.TileLayer("base",{
urlTemplate: 'http://webrd{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
subdomains: ['01', '02', '03', '04']
}))
this.map.config("spatialReference",{ projection : 'EPSG:3857' })
}
/**
* 显示天地图
*/
setSkyBaseLayer(){
this.map.removeLayer('skymarker')
this.map.setBaseLayer(new maptalks.TileLayer("base",{
crossOrigin: "Anonymous",
urlTemplate:'http://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=de0dc270a51aaca3dd4e64d4f8c81ff6',
subdomains:[1, 2, 3, 4],
}))
this.map.addLayer(new maptalks.TileLayer("skymarker",{
crossOrigin: "Anonymous",
urlTemplate:'http://t{s}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=de0dc270a51aaca3dd4e64d4f8c81ff6',
subdomains:[1, 2, 3, 4],
}))
this.map.config("spatialReference",{ projection : 'EPSG:3857' })
}
/**
* 绘制省会边界
* @param {Array} arr 省会坐标
* @param {Object} option 填充选项
* @param {String} option.lineColor 边样式
* @param {String} option.lineWidth 边宽度
* @param {String} option.polygonFill 填充颜色
* @param {String} option.polygonOpacity 透明度 0-1
*/
showBorder(arr,option){
this.provinces = arr
let options = {};
let defaultOption = {
'lineColor' : '#34495e',
'lineWidth' : 1,
'polygonFill' : 'rgb(0,0,0)',
'polygonOpacity' : 0.0
}
Object.assign(options, defaultOption, option);
for(let i=0;i<arr.length;i++){
console.log(JSON.parse(arr[i].points));
let polygon = new maptalks.MultiPolygon(
JSON.parse(arr[i].points)
, {
visible : true,
editable : true,
cursor : 'pointer',
shadowBlur : 0,
shadowColor : 'black',
draggable : false,
dragShadow : false, // display a shadow during dragging
drawOnAxis : null, // force dragging stick on a axis, can be: x, y
symbol: options
});
new maptalks.VectorLayer('vector'+i, polygon).addTo(this.map);
}
}
/**
* 设置某个省市的填充颜色,边框宽度,透明度等样式
* @param {*} name 省市的名称,或者代码
* @param {Object} option 样式选项
* @param {String} option.lineColor 边样式
* @param {String} option.lineWidth 边宽度
* @param {String} option.polygonFill 填充颜色
* @param {String} option.polygonOpacity 透明度 0-1
*/
setBorder(name,option){
this.map.config('pitch',45)
let options = {};
let defaultOption = {
'lineColor' : '#34495e',
'lineWidth' : 1,
'polygonFill' : 'rgb(0,0,0)',
'polygonOpacity' : 0.0
}
Object.assign(options, defaultOption, option);
for(let i=0;i<this.provinces.length;i++){
if(this.provinces[i].name === name
|| this.provinces[i].code === name){
let layer = this.map.getLayer('vector'+i)
let geos = layer.getGeometries()
for(let x=0;x<geos.length;x++){
let geo = geos[x]
geo.setSymbol(options)
}
break
}
}
}
/**
* 切换地图风格
* @param {Number} type 0:科技灰 1:科技蓝 2:黑夜
*/
changeMapFilter(type){
if(type === 0){
let baseLayer = this.map.getBaseLayer()
baseLayer.config('cssFilter','grayscale(100%)')//灰色
}else if(type === 1){
let baseLayer = this.map.getBaseLayer()
baseLayer.config('cssFilter','sepia(100%) invert(90%)')//蓝色
}else if(type === 2){
let baseLayer = this.map.getBaseLayer()
baseLayer.config('cssFilter','invert(100%)')//黑色
}
}
}
export {
maptalks, EasyMap, Tool, layers, EasyDrawTool, Geom, controls, InfoWindow, FlvJsPlayer
}