Vue+openLayers开发时的常用代码
- 加载天地图与arcgis server发布的切片服务
<template>
<div id="map" ref="rootmap"></div>
</template>
<script>
import "ol/ol.css";
import { Map, View } from "ol";
import TileLayer from "ol/layer/Tile";
import {OSM} from 'ol/source';
import XYZ from "ol/source/XYZ";
import {fromLonLat} from 'ol/proj';
export default {
data(){
return {
map:null
};
},
mounted() {
// const skpMapImg = "https://t{0-7}.tianditu.gov.cn/DataServer?T=img_c&x={x}&y={y}&l={z}&tk="; //天地图影像
// const skpMapCia = "https://t{0-7}.tianditu.gov.cn/DataServer?T=cia_c&x={x}&y={y}&l={z}&tk="; //天地图影像注记
const skpMapVec = "https://t{0-7}.tianditu.gov.cn/DataServer?T=vec_c&x={x}&y={y}&l={z}&tk="; //矢量天地图
const skpMapCva = "https://t{0-7}.tianditu.gov.cn/DataServer?T=cva_c&x={x}&y={y}&l={z}&tk="; //矢量天地图注记
const skpMapKey = "天地图密钥"; //天地图密钥
//这里用window['mapObj']替代this.map,切断对map对象的双向监控,提高速度
window['mapObj'] = new Map({
target: "map",
//地图控件
controls: defaultControls({ zoom: false }).extend([]),//这里是去掉自带的缩放按钮
layers: [
new TileLayer({
source: new XYZ({
projection: "EPSG:4326", //使用4326来加载4490坐标系
//经纬度投影
url: skpMapVec + skpMapKey
})
}),
new TileLayer({
source: new XYZ({
projection: "EPSG:4326", //使用4326来加载4490坐标系
//经纬度投影
url: skpMapCva + skpMapKey
})
}),
new TileLayer({
zIndex: 1,
source: new XYZ({
url:
'https://sldtptgis.zjwater.com/arcgis/rest/services/basemap/' +
'ZLSLVectorMap/MapServer/tile/{z}/{y}/{x}',
projection: "EPSG:4326", //使用4326来加载4490坐标系
})
},{ zoomOffset: 1 })
],
view: new View({
center: fromLonLat([120.527,27.817]),
// projection: "EPSG:4326", //mapview
zoom: 11,
maxZoom: 18,
minZoom: 10,
}),
});
},
};
</script>
- 请求arcgis服务后绘制要素
简单的网络请求模块:(封装在了名为mapRequest.js的文件中)
import axiosfrom 'axios'
export default function mapAxios(option) {
return new Promise((resolve,reject) => {
// 1. 创建axios实例
const instance = axios.create({
baseURL: "http://112.112.112.112:8008/arcgis/rest/services/",
timeout: 15000
});
// 2. 配置请求和响应拦截
instance.interceptors.request.use(config => {
// console.log('来到了request拦截success中');
// 2.1 当发送网络请求时, 在页面中添加一个loading组件, 作为动画
// 2.2 某些请求要求用户必须登录, 判断用户是否有token, 如果没有token跳转到login页面
// 2.3 对请求的参数进行序列化(看服务器是否需要序列化)
return config
},err => {
// console.log('来到了request拦截failure中');
return err
})
instance.interceptors.response.use(response => {
// console.log('来到了response拦截success中');
return response.data
},err => {
// console.log('来到了response拦截failure中');
// console.log(err);
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message = '请求错误'
break;
case 401:
err.message = '未授权的访问'
break;
}
}
return err
})
//2.传入对象进行网络请求
instance(option).then(res => {
// console.log(option)
resolve(res)
}).catch(err => {
reject(err)
})
})
}
二次封装的请求(封装在了名为loadMapserver.js的文件中)
import mapAxios from '../config/mapRequest'
export function queryMapserver(url,params) {
return mapAxios({
url,
params
})
}
组件中:
<template>
<div id="map" ref="rootmap">
<!-- 这里是气泡弹窗的dom -->
<div id="popup" class="ol-popup">
<a href="#" id="popup-closer" class="ol-popup-closer"></a>
<div id="popup-content" class="popup-content"></div>
</div>
<!-- --------------- -->
</div>
</template>
<script>
import "ol/ol.css"
import { Map, View, Feature, ol } from "ol"
import XYZ from 'ol/source/XYZ'
import { toStringHDMS } from "ol/coordinate"
import { fromLonLat, transform, toLonLat } from 'ol/proj'
import { defaults as defaultControls } from 'ol/control'
import Overlay from 'ol/Overlay';
import Point from 'ol/geom/Point';
// import GeoJSON from 'ol/format/GeoJSON'
import { Polygon, MultiPolygon } from "ol/geom"
import {Fill, Stroke, Icon, Style} from 'ol/style'
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer'
import {TileArcGISRest,Vector as VectorSource} from 'ol/source'
//请求服务画面用
import { queryMapserver } from '@/api/loadMapserver'
export default {
name:'MainMap',
components: {
},
props: {
},
data() {
return {
// map: null,
serviceLink: "http://112.112.112.112:8008/arcgis/rest/services/",
pointLayer: null, //点位图层
featuresArr: [] //点位要素数组
};
},
mounted() {
// const skpMapImg = "https://t{0-7}.tianditu.gov.cn/DataServer?T=img_c&x={x}&y={y}&l={z}&tk="; //天地图影像
// const skpMapCia = "https://t{0-7}.tianditu.gov.cn/DataServer?T=cia_c&x={x}&y={y}&l={z}&tk="; //天地图影像注记
const skpMapVec = "https://t{0-7}.tianditu.gov.cn/DataServer?T=vec_c&x={x}&y={y}&l={z}&tk="; //天地图影像
const skpMapCva = "https://t{0-7}.tianditu.gov.cn/DataServer?T=cva_c&x={x}&y={y}&l={z}&tk="; //天地图影像注记
const skpMapKey = "434967d31e3d3f9d396b2f4c4250b023"; //天地图密钥
//这里用window['mapObj']替代this.map,切断对map对象的双向监控,提高速度
window['mapObj'] = new Map({
target: "map",
//地图控件
controls: defaultControls({ zoom: false }).extend([]),
layers: [
new TileLayer({
source: new XYZ({
projection: "EPSG:4326"
//经纬度投影
url: skpMapVec + skpMapKey
})
}),
new TileLayer({
source: new XYZ({
projection: "EPSG:4326",
//经纬度投影
url: skpMapCva + skpMapKey
})
})
],
view: new View({
center: fromLonLat([121.000,27.000]),
zoom: 11,
maxZoom: 18,
minZoom: 10,
}),
});
//添加要素1
this.searchMap("border","2",'rgb(0,101,240)',3,'rgba(0,101,240,0.2)',this.showBorder)
//添加要素2
this.searchMap("river","0",'blue',1,'blue',this.showRiver)
},
methods: {
//这里是请求服务中子图层的全部要素的方法
searchMap(name,layer,bcolor,bwidth,fillcolor,callback) {
// console.log('searchMap');
//name为服务名,layer为子图层id,bcolor,bwidth为所绘边界颜色与宽度,fillcolor为填充色
//请求要素得到vectorSource
let mapUrl = name + "/MapServer/" + layer +"/query"
let param = {
where: "1=1",
outSR:4490,
inSR:4490,
maxAllowableOffset:0,
returnGeometry:true,
outFields:"*",
spatialRel:"esriSpatialRelIntersects",
f: "pjson",
}
let geojson = {}
queryMapserver(mapUrl,param).then(res => {
// console.log('queryMapserver');
let response = res.features
//将返回数据整饰成geojson
geojson = {
"type": "FeatureCollection",
'crs': {
'type': 'name',
'properties': {
'name': 'EPSG:4326',
},
},
"features": []
}
for(var i=0;i<response.length;i++) {
var row = response[i];
geojson.features.push({
"type": "Feature",
"geometry": {
"type": "MultiPolygon", //MultiPolygon
"coordinates": [row.geometry.rings]
}
})
}
// return geojson;
// this.showlayer(geojson,true,bcolor,bwidth,fillcolor)
callback(geojson,bcolor,bwidth,fillcolor)
})
},
//根据自己发的服务来画简单的面 作为初始方法
showBorder(geojson,bcolor,bwidth,fillcolor) {
// console.log(geojson);
//此处透明度靠fillcolor的颜色透明度来实现
if (geojson.features.length == 0) return false
let areaFeature = null
//设置要素样式
let styles = [
new Style({
stroke: new Stroke({
color: bcolor,
width: bwidth,
}),
fill: new Fill({
color: fillcolor,
}),
})
];
this.ruianLayer = new VectorLayer({
className: "ruianLayer",
zIndex: 2,
source: new VectorSource({
features: []
}),
style: styles,
});
for (let i = 0; i < geojson.features.length; i++) {
areaFeature = new Feature({
geometry: new MultiPolygon(
geojson.features[i].geometry.coordinates
).transform("EPSG:4326", "EPSG:3857")
});
this.ruianLayer.getSource().addFeatures([areaFeature])
}
window['mapObj'].addLayer(this.ruianLayer)
},
//根据自己发的服务来画简单的面 作为初始方法
showRiver(geojson,bcolor,bwidth,fillcolor) {
//此处透明度靠fillcolor的颜色透明度来实现
if (geojson.features.length == 0) return false
let areaFeature = null
//设置要素样式
let styles = [
new Style({
stroke: new Stroke({
color: bcolor,
width: bwidth,
}),
fill: new Fill({
color: fillcolor,
}),
})
];
this.riverLayer = new VectorLayer({
className: "riverLayer",
zIndex: 30,
source: new VectorSource({
features: []
}),
style: styles,
});
for (let i = 0; i < geojson.features.length; i++) {
areaFeature = new Feature({
geometry: new MultiPolygon(
geojson.features[i].geometry.coordinates
).transform("EPSG:4326", "EPSG:3857")
});
this.riverLayer.getSource().addFeatures([areaFeature])
}
window['mapObj'].addLayer(this.riverLayer)
},
//添加图层方法
showLayer(data) {
switch (data) {
case 1://加载全部
//每加入一个图层就要在这里写入添加的方法
window['mapObj'].addLayer(this.riverLayer)
break;
case 2://加载河道
//每加入一个图层就要在这里写入添加的方法
window['mapObj'].addLayer(this.riverLayer)
break;
}
},
//删除图层方法
removeAllLayer() {
//每加入一个图层就要在这里写入移除的方法
window['mapObj'].removeLayer(this.riverLayer)
}
},
};
</script>
<style lang="scss" scoped>
#map {
height: 100%;
width: 100%;
margin: 0;
position: relative;
}
/*隐藏ol的一些自带元素*/
.ol-attribution,
.ol-zoom {
display: none;
}
</style>
- 添加图标点位,并在图标上添加点击气泡弹窗
//加在上面的methods下
showPoint(coordinates) {
// 设置图层
this.pointLayer = new VectorLayer({
className: "pointLayer",
zIndex: 40,
source: new VectorSource()
});
// 添加图层
window['mapObj'].addLayer(this.pointLayer)
// 循环添加feature
for (let i = 0; i < coordinates.length; i++) {
// 创建feature,一个feature就是一个点坐标信息
let feature = new Feature({
name: "第一个点",
geometry: new Point(
fromLonLat([coordinates[i].x, coordinates[i].y])
)
});
feature.setStyle(this.getIcon(coordinates[i].type));
this.featuresArr.push(feature);
} // for 结束
// 批量添加feature
this.pointLayer.getSource().addFeatures(this.featuresArr);
const pointlayer = this.pointLayer;
// 使用变量存储弹窗所需的 DOM 对象
let container = document.getElementById("popup");
let closer = document.getElementById("popup-closer");
let content = document.getElementById("popup-content");
// 创建一个弹窗 Overlay 对象
this.overlay = new Overlay({
element: container, //绑定 Overlay 对象和 DOM 对象的
autoPan: true, // 定义弹出窗口在边缘点击时候可能不完整 设置自动平移效果
autoPanAnimation: {
duration: 250 //自动平移效果的动画时间 9毫秒
}
});
// 将弹窗添加到 map 地图中
window['mapObj'].addOverlay(this.overlay);
let _that = this;
/**
* 添加单击响应函数来处理弹窗动作
*/
window['mapObj'].on("click", function(evt,_that) {
pointlayer.getFeatures(evt.pixel).then((res) => {
let feature = res.length ? res[0] : undefined;
if (feature) {
let coordinates = feature.getGeometry().getCoordinates();
_that.overlay.setPosition(coordinates); //把 overlay 显示到指定的 x,y坐标
//这里获取到的feature是pointlayer图层点击位置的要素
// console.log(coordinates);
$(element).popover({
placement: 'top',
html: true,
content: feature.get('name'),
});
$(element).popover('show');
} else {
$(element).popover('dispose');
// console.log("no");
}
});
// "EPSG:3857", "EPSG:4326" 转换
let coordinate = transform(
evt.coordinate,
"EPSG:3857",
"EPSG:4326"
);
// 点击尺 (这里是尺(米),并不是经纬度);
let hdms = toStringHDMS(toLonLat(evt.coordinate)); // 转换为经纬度显示
content.innerHTML = `
<p>你点击了这里:</p>
<p>经纬度:<p><code> ${hdms} </code> <p>
<p>坐标:</p>X:${coordinate[0]} Y: ${coordinate[1]}`;
_that.overlay.setPosition(evt.coordinate); //把 overlay 显示到指定的 x,y坐标
});
/**
* 为弹窗添加一个响应关闭的函数
*/
closer.onclick = function() {
_that.overlay.setPosition(undefined);
closer.blur();
return false;
};
},
getIcon(type) {
let src = "";
type == "bule"
? (src = require("@/assets/images/patrol-img.png"))
: (src = require("@/assets/logo.png"));
var styleIcon = new Style({
// 设置图片效果
image: new Icon({
src: src,
anchor: [1, 1],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
scale: 0.2, //这个属性设置图片的大小
})
});
return styleIcon;
},
//之后定义
let coordinates = [
{ x: "120.527", y: "27.817", type: "lv" },
{ x: "120.527", y: "27.817", type: "bule" },
{ x: "120.527", y: "27.817", type: "lv" },
{ x: "120.527", y: "27.817", type: "bule" },
{ x: "120.527", y: "27.817", type: "lv" }
];
//然后执行
showPoint(coordinates )即可