前言

和高德地图,百度地图,腾讯地图,Arcgis一样,OpenLayers是一个用于开发WebGIS客户端的JavaScript包。它有自带的api在线说明官方文档:https://openlayers.org/。也有中文api网站:http://linwei.xyz/ol3-primer/ch01/index.html

  • openLayers依赖包npm安装: npm install ol –save

  • openLayers依赖包yarn安装: yarn add ol –save

一、openLayers实现电子图层离线加载

安装完成openLayers依赖之后首先要进行地图容器以及底图的绘制。底图是热力图等特效图层的基本承载。

现以vue框架为例:

// 底图根据id加载与div上 import "ol/ol.css"; // 官方地图源import OSM from "ol/source/OSM.js";import { Map, View } from "ol";import { defaults as defaultControls } from "ol/control";import {Tile as TileLayer} from "ol/layer";import DragPan from 'ol/interaction/DragPan'//先在项目中引用此包export default {data() {return {map: null,};},created() {},mounted() {this.initMap();},methods: {// 初始化地图initMap() {// 地图底图源使用OSM,当然也可以用其他风格的源const raster = new TileLayer({source: new OSM(),});this.map = new Map({target: "map",controls: defaultControls({zoom: false, // 隐藏缩放按钮,false为隐藏,true为显示}).extend([]),layers: [raster],view: new View({// 除了EPSG:4326坐标系还有EPSG:3857,统一即可projection: "EPSG:4326",center: [11.964483155944814,13.87500286102295],zoom: 0,// maxZoom: 19,// minZoom: 5,}),});// 禁止地图拖拽this.disablePanMove();// 禁用鼠标滚轮事件this.map.getView().setMinZoom(0);this.map.getView().setMaxZoom(0);},// 禁用地图拖拽时间disablePanMove(){let pan = null;this.map.getInteractions().forEach(element => {if (element instanceof DragPan) {pan = element}});pan.setActive(false); //false禁止拖拽,true允许拖拽}},};.map{width: 100%;height:600px;}

地图效果:

以上是在线地图加载的全部示例代码,实际上电子地图源除了使用官方地图源还可以使用其他地图源: http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}

const raster = new TileLayer({source: new XYZ({url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}", }), });

呈现效果:

使用其他源时候需要将引入的osm官方源替换为可以自动获取当前展示位置xyz的依赖:

import OSM from “ol/source/OSM.js”;

替换为:

import XYZ from “ol/source/XYZ”;

以上都是在线的时候,当运行环境为内网,无法连接外部互联网的时候呢?

这个时候需要进行离线地图加载操作了。首先下载离线地图下载器,在这里推荐一款免安装地图图片下载器:

https://download.csdn.net/download/qq_39958056/87450369?spm=1001.2014.3001.5503

下载以后的样式:

将这些数据有static静态目录的放在static静态目录下,没有的放在public 目录下:

这时候只需要把电子地图的源替换为放在public目录下的存放底图图片的文件夹即可:

const raster = new TileLayer({source: new XYZ({url:'/roadmap/{z}/{x}/{y}.png',//本例中地图瓦片保存在public目录下的roadmap文件夹目录下}),});

展示效果:

离线地图加载成功!

二、openLayers实现热力图层绘制及加载

添加热力图所需要引用依赖:

import {Map, View, Feature} from "ol";import "ol/ol.css";import VectorLayer from "ol/layer/Vector";import XYZ from "ol/source/XYZ";import {Heatmap as HeatmapLayer, Tile as TileLayer} from 'ol/layer.js'import VectorSource from 'ol/source/Vector.js'

绘制底图方法:

initMap() {const raster = new TileLayer({source: new XYZ({url:'/roadmap/{z}/{x}/{y}.png',//本例中地图瓦片保存在当前静态资源目录下}),});this.map = new Map({target: 'map',// 在layers中添加自己所需要的图层,这里不做添加,只添加热力图层layers: [raster],view: new View({projection: "EPSG:4326",// EPSG:3857center: [120.92898835156248, 23.6828209384589], // 中心点zoom: 7, // 地图放大倍数minZoom: 7 // 地图最小倍数}),});}

添加热力图方法:

initMap() {const raster = new TileLayer({source: new XYZ({url:'/roadmap/{z}/{x}/{y}.png',//本例中地图瓦片保存在当前静态资源目录下}),});this.map = new Map({target: 'map',// 在layers中添加自己所需要的图层,这里不做添加,只添加热力图层layers: [raster],view: new View({projection: "EPSG:4326",// EPSG:3857center: [120.92898835156248, 23.6828209384589], // 中心点zoom: 7, // 地图放大倍数minZoom: 7 // 地图最小倍数}),});}addHeatArea(heatData) {// 创建一个热力图层let vector = new HeatmapLayer({// 矢量数据源source: new VectorSource({features: (new GeoJSON()).readFeatures(heatData, {dataProjection: 'EPSG:4326',featureProjection: 'EPSG:4326'}),}),blur: 20, // 模糊尺寸radius: 20 // 热点半径});this.map.addLayer(vector); // 将热力图添加在地图上},

热力图假数据:

// 热力图假数据,照这个形式来进行传输就行heatData: {type: 'FeatureCollection',features: [{type: 'Point', 'coordinates': [120.36293,23.53477], count: 100},{type: 'Point', 'coordinates': [120.45631, 23.76611], count: 19},{type: 'Point', 'coordinates': [120.78590, 23.51464], count: 419},{type: 'Point', 'coordinates': [121.58241, 25.06584], count: 319},{type: 'Point', 'coordinates': [120.3903, 22.73204], count: 719},{type: 'Point', 'coordinates': [121.09901, 22.80292], count: 519},{type: 'Point', 'coordinates': [120.22011, 23.10624], count: 319},{type: 'Point', 'coordinates': [120.67604, 24.26258], count: 139},{type: 'Point', 'coordinates': [121.56593, 24.01208], count: 129},]},

呈现效果:

三、openLayers实现行政区划边界绘制

进行行政区划绘制所需要引用依赖:

import {Map, View, Feature} from "ol";import {Style, Stroke, Fill} from "ol/style";import {Polygon, MultiPolygon} from "ol/geom"import "ol/ol.css";import VectorLayer from "ol/layer/Vector";import XYZ from "ol/source/XYZ";import {Tile as TileLayer} from 'ol/layer.js'import VectorSource from 'ol/source/Vector.js'import GeoJSON from 'ol/format/GeoJSON'

底图绘制参见上文。

行政区划绘制方法:

// 设置区域addArea(geo) {let features = [];geo.forEach((g) => {let lineData = g.geometry;let routeFeature = "";if (lineData.type === "MultiPolygon") {routeFeature = new Feature({geometry: new MultiPolygon(lineData.coordinates),});} else if (lineData.type === "Polygon") {routeFeature = new Feature({geometry: new Polygon(lineData.coordinates),});}routeFeature.setStyle(new Style({fill: new Fill({color: "#4e98f444", //填充颜色}),stroke: new Stroke({width: 1, //边界宽度color: [71, 137, 227, 1], //边界颜色}),}));features.push(routeFeature);});// 设置图层this.routeLayer = new VectorLayer({source: new VectorSource({features: features,}),});// 添加图层this.map.addLayer(this.routeLayer);},

实现效果:

边界json数据格式示例:

{"type": "FeatureCollection","features": [{"type": "Feature","properties": {"adcode": 110101,"name": "东城区","center": [116.418757,39.917544],"centroid": [116.416739,39.912912],"childrenNum": 0,"level": "district","acroutes": [100000,110000],"parent": {"adcode": 110000}},"geometry": {"type": "MultiPolygon",// 边界坐标数据,数据过多不一一展示"coordinates": [[[[116.387664,39.960923],[116.38948,39.961038]]]]}}]}

想获取行政区边界数据可以在此网站获取:

http://datav.aliyun.com/tools/atlas/#&lat=35.24561909420681&lng=104.2822265625&zoom=4

四、openLayers实现地图标点

进行地图标点需要引用依赖:

import {Map, View, Feature} from "ol";import {Style, Icon, Text, Fill} from "ol/style";import {Point} from "ol/geom"import "ol/ol.css";import VectorLayer from "ol/layer/Vector";import XYZ from "ol/source/XYZ";import {Tile as TileLayer} from 'ol/layer.js'import VectorSource from 'ol/source/Vector.js'import pointImg from '../assets/point.png'

底图绘制参见上文。

openLayers打点方法:

addIconMarker(data) {let features = []; // 标点列表存放路径data.map((item)=>{const marker = new Feature({name:item.name, // 标点的附属属性可以以该形式放在此处,如type:item.typegeometry: new Point(item.location)});marker.setStyle(new Style({image: new Icon({anchor: [0.5, 1],scale: 0.05, // 图片放缩程度src: pointImg // 标点图片路径 }), // 设置图片下面显示字体的样式和内容 text: new Text({text: item.name,// 添加文字描述font: '14px font-size', // 设置字体大小fill: new Fill({// 设置字体颜色color: [71, 137, 227, 1]}),offsetY: 10// 设置文字偏移量})})); })const vectorLayer = new VectorLayer({source: new VectorSource({features: features,})});this.map.addLayer(vectorLayer);}

打点假json数据格式示例:

pointData: [{name: '台北',location: [121.50,25.03]},{name: '高雄',location: [120.28,22.62]},{name: '台南',location: [120.20,23.00]},{name: '台中',location: [120.67,24.15]},{name: '基隆',location: [121.73,25.13]},{name: '花莲',location: [121.60,23.98]},{name: '桃园',location: [121.30,24.97]},{name: '新竹',location: [120.95,24.82]},{name: '嘉义',location: [120.43,23.48]},]

实现效果:

图标点击事件确定:

底层逻辑:鼠标点击地图先触发地图的点击事件,把该点击事件用方法forEachFeatureAtPixel进行判断,如果是点击的图标则会返回图标以及其属性,若是点击的图片的其他地方(非标点)则会返回undefined。

该地图点击事件放于mounted()里面也可以放进initMap,也就是创建地图底图方法里面;

// 地图点击触发事件this.map.on("click", e=>{// 判断是不是移动到图标之上const feature = this.map.forEachFeatureAtPixel(e.pixel,feature=>{return feature;});// 如果移动到图标上就继续进行下一步操作if(feature){// 获取到上面预先设置的属性console.info(feature.values_.name);}});

五、openLayers实现文字标注

实现文字标注和打点同理,只不过不需要加载图片。

但是注意,所有的不管是带点的文字标识还是不带点的,只能以字符串形式呈现,不能使用字符串夹杂number形式。

进行文字标注需要引用依赖:

import {Map, View, Feature} from "ol";import {Style, Text, Fill} from "ol/style";import {Point} from "ol/geom"import "ol/ol.css";import VectorLayer from "ol/layer/Vector"; // 矢量地图import XYZ from "ol/source/XYZ";import {Tile as TileLayer} from 'ol/layer.js' // 电子地图import VectorSource from 'ol/source/Vector.js' // 矢量地图源

底图绘制参见上文。

openLayers打点方法:

addTextMarker(data) {let features = []; // 文字标点列表存放路径data.map((item)=>{const marker = new Feature({name:item.name, // 标点的附属属性可以以该形式放在此处,如type:item.typegeometry: new Point(item.location)});marker.setStyle(new Style({ // 进行文字标点的字体的样式和内容 text: new Text({text: item.name,// 添加文字描述font: '14px font-size', // 设置字体大小fill: new Fill({// 设置字体颜色color: [71, 137, 227, 1]}),offsetY: 0// 设置文字偏移量})})); })const vectorLayer = new VectorLayer({source: new VectorSource({features: features,})});this.map.addLayer(vectorLayer);}

打点假json数据格式示例:

pointData: [{name: '台北',location: [121.50,25.03]},{name: '高雄',location: [120.28,22.62]},{name: '台南',location: [120.20,23.00]},{name: '台中',location: [120.67,24.15]},{name: '基隆',location: [121.73,25.13]},{name: '花莲',location: [121.60,23.98]},{name: '桃园',location: [121.30,24.97]},{name: '新竹',location: [120.95,24.82]},{name: '嘉义',location: [120.43,23.48]},]

实现效果:

六、openLayers实现地图弹窗

实现地图弹窗的依赖引入:

import {Map, View, Feature, Overlay} from "ol"; // 比绘制底图多引入了一个Overlayimport "ol/ol.css";import VectorLayer from "ol/layer/Vector";import XYZ from "ol/source/XYZ";import {Tile as TileLayer} from 'ol/layer.js'import VectorSource from 'ol/source/Vector.js'

加载地图弹窗的dom结构:

// 底图根据id加载与div上/*div中可以放置弹窗内容*/

地图弹窗的创建和加载要放在创建底图的方法里面:

initMap() {// 电子地图实例创建const raster = new TileLayer({source: new XYZ({url:'/roadmap/{z}/{x}/{y}.png',//本例中地图瓦片保存在当前静态目录下}),});// 弹窗实例的创建this.overLayer = new Overlay({element:this.$refs.popOut, // 弹窗所加载到dom结构autoPan:true, // 若弹窗在底图边缘,底图会移动// 底图移动动画autoPanAnimation:{duration:250}});this.map = new Map({target: 'map', // 地图实例所加载上的dom结构// 在layers中添加自己所需要的图层layers: [raster],overlays:[this.overLayer], // 弹窗图层添加view: new View({projection: "EPSG:4326", // 视图所使用的坐标系// EPSG:3857center: [120.92898835156248, 23.6828209384589], // 中心点zoom: 7, // 地图放大倍数minZoom: 7 // 地图最小倍数}),});// 地图点击触发事件this.map.on("click", e=>{// 判断是不是移动到图标之上const feature = this.map.forEachFeatureAtPixel(e.pixel,feature=>{return feature;});// 如果移动到图标上就继续进行下一步操作if(feature){// 设定弹窗位置this.overLayer.setPosition(e.coordinate);// 获取到上面预先设置的属性,可以根据获取预先设置的属性来改变弹窗内容console.info(feature.values_.name);}else{// 取消弹窗显示this.overLayer.setPosition(undefined);}});},

不光如此,还得有实现地图打点的方法,地图打点方法参见上文。

实现地图弹窗的所有代码:

// 底图根据id加载与div上/*div中可以放置弹窗内容*/import {Map, View, Feature,Overlay} from "ol";import {Style, Icon, Text, Fill} from "ol/style";import {Point} from "ol/geom";import "ol/ol.css";import VectorLayer from "ol/layer/Vector"; // 矢量图层import OSM from "ol/source/OSM.js"; // 官方电子地图源import {Tile as TileLayer} from 'ol/layer.js' // 电子地图import VectorSource from 'ol/source/Vector.js' // 矢量地图源import pointImg from '../assets/point.png' // 打点图片export default {name: 'mapDemo',data() {return {pointImg,map: null,overLayer:null,// 点数据pointData: [{name: '台北',location: [121.50,25.03]},{name: '高雄',location: [120.28,22.62]},{name: '台南',location: [120.20,23.00]},{name: '台中',location: [120.67,24.15]},{name: '基隆',location: [121.73,25.13]},{name: '花莲',location: [121.60,23.98]},{name: '桃园',location: [121.30,24.97]},{name: '新竹',location: [120.95,24.82]},{name: '嘉义',location: [120.43,23.48]},],}},methods: {initMap() {// 电子地图实例创建const raster = new TileLayer({source: new XYZ({url:'/roadmap/{z}/{x}/{y}.png',//本例中地图瓦片保存在当前静态目录下}),});// 弹窗实例的创建this.overLayer = new Overlay({element:this.$refs.popOut, // 弹窗所加载到dom结构autoPan:true, // 若弹窗在底图边缘,底图会移动// 底图移动动画autoPanAnimation:{duration:250}});this.map = new Map({target: 'map', // 地图实例所加载上的dom结构// 在layers中添加自己所需要的图层layers: [raster],overlays:[this.overLayer], // 弹窗图层添加view: new View({projection: "EPSG:4326", // 视图所使用的坐标系// EPSG:3857center: [120.92898835156248, 23.6828209384589], // 中心点zoom: 7, // 地图放大倍数minZoom: 7 // 地图最小倍数}),});// 地图点击触发事件this.map.on("click", e=>{// 判断是不是移动到图标之上const feature = this.map.forEachFeatureAtPixel(e.pixel,feature=>{return feature;});// 如果移动到图标上就继续进行下一步操作if(feature){// 设定弹窗位置this.overLayer.setPosition(e.coordinate);// 获取到上面预先设置的属性,可以根据获取预先设置的属性来改变弹窗内容console.info(feature.values_.name);}else{// 取消弹窗显示this.overLayer.setPosition(undefined);}});},// 地图打点方法addIconMarker(data) {let features = []; // 标点列表存放路径data.map((item)=>{const marker = new Feature({name:item.name, // 标点的附属属性可以以该形式放在此处,如type:item.typegeometry: new Point(item.location)});marker.setStyle(new Style({image: new Icon({anchor: [0.5, 1],scale: 0.05, // 图片放缩程度src: pointImg // 标点图片路径}),// 设置图片下面显示字体的样式和内容text: new Text({text: item.name,// 添加文字描述font: '14px font-size', // 设置字体大小fill: new Fill({// 设置字体颜色color: [71, 137, 227, 1]}),offsetY: 10// 设置文字偏移量})}));features.push(marker)});const vectorLayer = new VectorLayer({source: new VectorSource({features: features,})});this.map.addLayer(vectorLayer);}},mounted() {this.initMap();this.addIconMarker(this.pointData)}}.map {width: 771px;height: 474px;}.pop{width: 200px;height: 80px;background-color: white;}

实现效果:

点击点后控制台输出数据:

此时弹窗是左上角贴近点击的点,如果想让弹窗显示在点的正上方只需要设置一下弹窗的css样式即可:

.pop{width: 200px;height: 80px;position:absolute;left:-100px;bottom:5px;background-color: white;}

七、openLayers实现地图绘线

进行地图绘线绘制所需要引用依赖:

import {Map, View, Feature} from "ol";import {Style, Stroke, Fill} from "ol/style";import {LineString} from "ol/geom"import "ol/ol.css";import VectorLayer from "ol/layer/Vector";import XYZ from "ol/source/XYZ";import {Tile as TileLayer} from 'ol/layer.js'import VectorSource from 'ol/source/Vector.js'

底图绘制参见上文。

openLayers地图绘制多条线段方法:

drawLine(coordinates) {// coordinates:坐标数据if(coordinates && coordinates.length>0){ let features = []; // 线条样式存放路径coordinates.map(item =>{if(item.length >1 ){let feature = new Feature({geometry:new LineString(item)});features.push(feature)}});let vectorLayer = new VectorLayer({source: new VectorSource({features:features,}),style: new Style({// 线段颜色stroke: new Stroke({color: "blue",width: 5})})});this.map.addLayer(vectorLayer);}},

地图绘线假json数据格式示例:

linePointData:[[[120.45631, 23.76611], // 起点坐标[120.78590, 23.51464] // 终点坐标,其他坐标可放进起终点坐标之间],[[120.45631, 23.76611],[120.78590, 23.51464]],]

实现效果:

八、openLayers常见地图实例

  • https://openlayers.org/en/master/examples/ openlayers地图官方实例网站

  • http://openlayers.org/en/master/examples/epsg-4326.html — 标尺

  • http://openlayers.org/en/master/examples/export-map.html — 截图

  • http://openlayers.org/en/master/examples/export-pdf.html — 导出PDF

  • http://openlayers.org/en/master/examples/extent-interaction.html — 国界线

  • http://openlayers.org/en/master/examples/feature-animation.html — 动态弹圆圈

  • http://openlayers.org/en/master/examples/feature-move-animation.html — 圆点按路线跑动

  • http://openlayers.org/en/master/examples/flight-animation.html — 散射图

  • http://openlayers.org/en/master/examples/full-screen-source.html — 全屏地图

  • http://openlayers.org/en/master/examples/full-screen.html — 全屏地图2

  • http://openlayers.org/en/master/examples/geojson.html — 画几何图形

  • http://openlayers.org/en/master/examples/geolocation-orientation.html — 定位 不能定位

  • http://openlayers.org/en/master/examples/geolocation.html — 定位2 可以定位到

  • http://openlayers.org/en/master/examples/getfeatureinfo-image.html — 获取鼠标点击位置的详细信息

  • http://openlayers.org/en/master/examples/getfeatureinfo-tile.html — 获取鼠标点击位置的详细信息(瓦片层)

  • http://openlayers.org/en/master/examples/graticule.html — 有经纬线的地图

  • http://openlayers.org/en/master/examples/heatmap-earthquakes.html — 热力能量图

  • http://openlayers.org/en/master/examples/hit-tolerance.html — 误差

  • http://openlayers.org/en/master/examples/icon-color.html — 图块地图

  • http://openlayers.org/en/master/examples/icon.html — 图块地图(打标记)

  • http://openlayers.org/en/master/examples/icon-negative.html — 地点标记

  • http://openlayers.org/en/master/examples/image-filter.html — 绿色植被

  • http://openlayers.org/en/master/examples/image-vector-layer.html — 点选国家,边界线画出来

  • http://openlayers.org/en/master/examples/kml-earthquakes.html — 地震带

  • http://openlayers.org/en/master/examples/kml-timezones.html — 时间轴地图

  • http://openlayers.org/en/master/examples/kml.html — 矢量地图

  • http://openlayers.org/en/master/examples/layer-clipping.html — 图形裁剪地图

  • http://openlayers.org/en/master/examples/layer-extent.html — 标记位置

  • http://openlayers.org/en/master/examples/layer-spy.html — 放大镜效果

  • http://openlayers.org/en/master/examples/layer-swipe.html — 明亮 阴影面地图

  • http://openlayers.org/en/master/examples/layer-z-index.html — z坐标轴

  • http://openlayers.org/en/master/examples/line-arrows.html — 画带箭头的折线图(双击鼠标停止划线)

  • http://openlayers.org/en/master/examples/lazy-source.html — 填充和置空地图

  • http://openlayers.org/en/master/examples/localized-openstreetmap.html — 街道图

  • http://openlayers.org/en/master/examples/measure.html — 测量直线距离

  • http://openlayers.org/en/master/examples/modify-features.html — 点击shift键,拉动鼠标,放大地图

  • http://openlayers.org/en/master/examples/mouse-position.html — 获取鼠标在地图上的位置

  • http://openlayers.org/en/master/examples/moveend.html — 获取地图上下左右的位置

  • http://openlayers.org/en/master/examples/overlay.html — 弹窗显示鼠标点击位置的坐标位置

  • http://openlayers.org/en/master/examples/popup.html — 弹窗显示鼠标点击位置的坐标位置

  • http://openlayers.org/en/master/examples/overviewmap-custom.html — 小窗口显示小地图

  • http://openlayers.org/en/master/examples/overviewmap.html — 小窗口显示小地图

  • http://openlayers.org/en/master/examples/preload.html — 双DIV显示地图(不同尺寸)

  • http://openlayers.org/en/master/examples/reprojection.html — 切换地图参数

  • http://openlayers.org/en/master/examples/reusable-source.html — 切片覆盖,换切片

  • http://openlayers.org/en/master/examples/sea-level.html — 水位

  • http://openlayers.org/en/master/examples/select-features.html — 鼠标点击方式

  • http://openlayers.org/en/master/examples/shaded-relief.html — 光线角度

  • http://openlayers.org/en/master/examples/side-by-side.html — 双DIV显示

  • http://openlayers.org/en/master/examples/snap.html — 标记地图方式切换

  • http://openlayers.org/en/master/examples/ — 地图切换到另一个DIV显示

  • http://openlayers.org/en/master/examples/tile-load-events.html –监听点击,有条状态线

  • http://openlayers.org/en/master/examples/tileutfgrid.html — 鼠标滑过,显示国旗

  • http://openlayers.org/en/master/examples/tilejson.html — tilejson 例子

  • http://openlayers.org/en/master/examples/topolis.html — 画点,并用线条连接起来

  • http://openlayers.org/en/master/examples/translate-features.html — 切换国家

  • http://openlayers.org/en/master/examples/vector-esri-edit.html — 地图上划线

  • http://openlayers.org/en/master/examples/vector-labels.html — 改变 地图参数

  • http://openlayers.org/en/master/examples/vector-layer.html — 地图画边线

  • http://openlayers.org/en/master/examples/vector-osm.html — 三维地图

  • http://openlayers.org/en/master/examples/vector-wfs.html — wfs地图

  • http://openlayers.org/en/master/examples/wms-capabilities.html — wms 性能分析

  • http://openlayers.org/en/master/examples/zoomslider.html –滑动条,改变大小