vue+ol实现 ol 地图加载geojson
生活随笔
收集整理的這篇文章主要介紹了
vue+ol实现 ol 地图加载geojson
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、背景
公司需要個簡單的二維底圖,加載點線面數據,為了省時間就用openlayers框架寫一個簡單的加載方法,openlayers核心包含Map對象、View視圖、Layer圖層、Source來源、Feature等特征
二、加載配置
在正常的vue系統的package.json文件中引入openlayer的包
"dependencies": {..."ol": "^6.6.1" }三、地圖初始化
新建一個組件??map/index.vue文件,里面核心代碼如下
import esb from '@/plugins/esb' import 'ol/ol.css' import Map from 'ol/Map' import View from 'ol/View' import { getWidth,getCenter} from 'ol/extent' import TileLayer from 'ol/layer/Tile' import WMTS from 'ol/source/WMTS' import XYZ from 'ol/source/XYZ' import WMTSTileGrid from 'ol/tilegrid/WMTS' import Projection from 'ol/proj/Projection' import VectorSource from 'ol/source/Vector' import VectorLayer from 'ol/layer/Vector' import Feature from 'ol/Feature' // import Point from 'ol/geom/Point' import { Draw } from 'ol/interaction' import { Style, Circle, Stroke, Fill } from 'ol/src/style' import WKT from 'ol/format/WKT' import GeoJSON from 'ol/format/GeoJSON' import { GEOJSON_BL } from '@/const/data/beilin.js'地圖初始化 方法: init () { // 初始化地圖// 矢量圖層const projection = new Projection({code: 'EPSG:4326',extent: [-180, -90, 180, 90],metersPerUnit: 2 * Math.PI * 6378137 / 360})/* const projectionExtent = projection.getExtent()const size = getWidth(projectionExtent) / 256const resolutions = new Array(18)const matrixIds = new Array(18)for (let z = 0; z < 18; ++z) {resolutions[z] = size / Math.pow(2, z + 1)matrixIds[z] = z + 1}// 省級節點提供的瓦片總共14級,從7到20const resolutions2 = new Array(20)const matrixIds2 = new Array(20)for (let z = 0; z < 20; ++z) {resolutions2[z] = size / Math.pow(2, z)matrixIds2[z] = z}const orgin = [-180, 90]*/this.vectorLayer = new VectorLayer({source: new VectorSource(),style: new Style({stroke: new Stroke({width: 2,color: [242, 114, 60, 1],lineDash: [1, 2, 3, 4, 5, 6]}),fill: new Fill({color: [242, 114, 60, 0.2]}),image: new Circle({// 點的顏色fill: new Fill({COLOR: '#f60404',color: [246, 4, 4, 1]}),stroke: new Stroke({color: [242, 114, 60, 1]}),// 圓形半徑radius: 5})})})this.GGLWLayer =new TileLayer({source:new XYZ({url:"http://t4.tianditu.com/DataServer?T=vec_c&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d"}),visible: false});this.GGLayer =new TileLayer({source:new XYZ({//url:"http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d"url:"http://globescenetiles.frp.trmap.cn/L8/{z}/{x}/{y}.png"}),visible: false});this.TDTLayer =new TileLayer({source:new XYZ({url:"http://t4.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d"})});this.zjLayer =new TileLayer({source:new XYZ({url:"http://t4.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d"})});this.map = new Map({layers: [this.TDTLayer,this.GGLayer,// this.GGLWLayer,this.vectorLayer,this.zjLayer],target: 'map',view: new View({center: [106.814931000, 34.945231000, 16000],projection: projection,minZoom: 4,maxZoom: 21,// extent : maxExtent, //限定到地圖視圖拖動范圍zoom: 5 // 地圖初始化的縮放級別})})},四、加載geojson
import { GEOJSON_BL } from '@/const/data/beilin.js'// 添加GeoJOSNaddGeoJSON () {this.clearGeoJSON()let source = new VectorSource({// 準備好的GeoJSONfeatures: new GeoJSON().readFeatures(GEOJSON_BL)})debuggerthis.geoLayer = new VectorLayer({source: source,// 設置樣式,邊框和填充style: new Style({stroke: new Stroke({color: 'green',width: 5}),fill: new Fill({color: 'rgba(255, 255, 0, 0.5)'})})})// 添加GeoJSON到map上this.map.addLayer(this.geoLayer)// 地圖視圖縮小一點const view = this.map.getView()view.setZoom(9)},// 清除GeoJSONclearGeoJSON () {if (this.geoLayer) {this.map.removeLayer(this.geoLayer)this.geoLayer = null}// 清除之后將地圖中心還原const view = this.map.getView()view.setCenter([106.814931000, 34.945231000, 16000])view.setZoom(12)}五、底圖切換demo
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>openlayers</title><script src="js/ol.js"></script><link rel="stylesheet" type="text/css" href="css/ol.css"/></head><body><button type="button" onclick="changeMap(1)">衛星地圖</button><button type="button" onclick="changeMap(2)">路網地圖</button><div id="map" class="map" style="width: 100%;"></div></body><script type="text/javascript">// 改為天地圖地圖var mlayer1 = new ol.layer.Tile({source: new ol.source.XYZ({url:"http://t4.tianditu.com/DataServer?T=vec_c&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d"}),visible: true});// 改為天地圖影像var mlayer2 = new ol.layer.Tile({source: new ol.source.XYZ({url:"http://t4.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d"}),visible: false});var map = new ol.Map({layers: [mlayer1,mlayer2],target: 'map',controls: ol.control.defaults({attributionOptions: {collapsible: false}}),view: new ol.View({center: [0, 0],zoom: 2})});// 切換地圖function changeMap(data){if(data==1){mlayer1.setVisible(true);mlayer2.setVisible(false);}else {mlayer1.setVisible(false);mlayer2.setVisible(true);}}</script> </html>六、繪制、修改點線面
point () {const m = thism.isShow = falsem.type = 'Point'm.drawMap(m.type) },polygon () {const m = thism.isShow = falsem.type = 'Polygon'this.drawMap(m.type) }, drawMap (type) {document.oncontextmenu = function () {return false}const m = thism.map.removeInteraction(this.draw)this.vectorLayer.getSource().clear()m.draw = new Draw({source: this.vectorLayer.getSource(),type: type,stopClick: true, // 繪制時禁用點擊事件style: this.getDrawingStyle()})m.draw.on('drawend', e => {// let coordinates = e.feature.getGeometry().getCoordinates();m.feature = e.featurevar a = new WKT()m.wkt = a.writeGeometry(m.feature.getGeometry())m.map.removeInteraction(m.draw)})this.map.addInteraction(m.draw) },getDrawingStyle () {return new Style({stroke: new Stroke({width: 2,color: [239, 176, 19, 1],lineDash: [1, 2, 3, 4, 5, 6]}),fill: new Fill({color: [239, 176, 19, 0.2]}),image: new Circle({// 點的顏色fill: new Fill({color: [246, 4, 4, 1]}),stroke: new Stroke({color: [239, 176, 19, 1]}),// 圓形半徑radius: 5})}) },七、完善各種功能后,完整代碼如下:
map/index.vue
<template><div style="width:100%; height: 100%; position: relative;" v-if="areaShow"><div id="map" style="width:100%; height: 100%;" /><span @click="getGeoHandle()" /><div v-if="isButton" style="position: absolute;right:12px;top:12px"><p v-if="isShow" style="margin-top: 10px"><Button type="primary" size="small" @click="point()">繪制點</Button><Button type="primary" size="small" @click="polygon()">繪制面</Button><Button type="warning" size="small" @click="clearDraw()">重置</Button></p><p v-else style="margin-top: 10px"><Button type="primary" size="small" @click="submit">確定</Button><Button type="warning" size="small" @click="reset()">重置</Button></p></div></div> </template><script>import esb from '@/plugins/esb' import 'ol/ol.css' import Map from 'ol/Map' import View from 'ol/View' import TileLayer from 'ol/layer/Tile' import XYZ from 'ol/source/XYZ' import VectorSource from 'ol/source/Vector' import VectorLayer from 'ol/layer/Vector' import Feature from 'ol/Feature' import { Draw } from 'ol/interaction' import { Style, Circle, Stroke, Fill,Text} from 'ol/src/style' import WKT from 'ol/format/WKT' import GeoJSON from 'ol/format/GeoJSON' export default {name: 'Map',props: ['areaShow', 'geometrys', 'isButton','layerid','geojsonurl','hightFeature'],data () {return {fullscreen: true,lon: '',lat: '',map: null,type: null,style: null,feature: null,wkt: null,isShow: true}},watch: {areaShow (v) {if (v) {this.$nextTick(() => {if (!this.map) {this.init()}})}},layerid(v){if(v){var m =this;m.changeMap(v);}},geojsonurl:{immediate:true,handler(v){var m =this;if(v){m.addGeoJSON(v)}else{m.clearGeoJSON()}}},geometrys(v){if(v && v.length>0){this.loadGeometrys(v)}else{this.clearDraw()}},hightFeature(v){if(v){this.addHeighLight(v)}else{this.clearHeighLight()}}},mounted () {if (this.areaShow) {if (!this.map) {this.init()}};},methods: {init () { // 初始化地圖// 矢量圖層this.vectorLayer = new VectorLayer({source: new VectorSource(),style: new Style({stroke: new Stroke({width: 2,color: [242, 114, 60, 1],lineDash: [1, 2, 3, 4, 5, 6]}),fill: new Fill({color: [242, 114, 60, 0.2]}),image: new Circle({// 點的顏色fill: new Fill({COLOR: '#f60404',color: [246, 4, 4, 1]}),stroke: new Stroke({color: [242, 114, 60, 1]}),// 圓形半徑radius: 5})})})//高亮圖層this.highlightLayer = new VectorLayer({source: new VectorSource(),style: this.getHeightStyle()})this.yxLayer =new TileLayer({source:new XYZ({//url:"http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d"url: this.$root.YXLAYERURL ||"http://globescenetiles.frp.trmap.cn/L8/{z}/{x}/{y}.png"}),visible: false});this.slLayer =new TileLayer({source:new XYZ({// url:"http://t4.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d"url: this.$root.SLLAYERURL || "http://globescenetiles.frp.trmap.cn/L8vec/{z}/{x}/{y}.png"})});this.zjLayer =new TileLayer({source:new XYZ({url:"http://t4.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d"}),visible: this.$root.SHOWZJLAYER==true || false});this.map = new Map({layers: [this.yxLayer,this.slLayer,this.vectorLayer,this.zjLayer,this.highlightLayer],target: 'map',view: new View({center: [106.814931000, 34.945231000, 16000],projection: 'EPSG:4326',minZoom: 4,maxZoom: 21,// extent : maxExtent, //限定到地圖視圖拖動范圍zoom: 5 // 地圖初始化的縮放級別})})},loadGeometrys(features){this.clearDraw();var gemos = JSON.parse(JSON.stringify(features));if(gemos.length>1){gemos.forEach(e=>{var feature = new GeoJSON().readFeature(e, {featureProjection: "EPSG:4326" //規定要素以哪種坐標顯示});var style = this.getlightStyle();feature.setStyle(style);this.vectorLayer.getSource().addFeature(feature)})}const view = this.map.getView()const extent = this.vectorLayer .getSource().getExtent();//定位范圍view.fit(extent);},submit () {if (this.wkt == null) {this.$message({type: 'error',message: '不能保存空位置'})}document.oncontextmenu = function () {return true}return esb.$emit('MapHandle', { geometry: this.wkt })},reset () {this.isShow = truethis.vectorLayer.getSource().clear()},point () {const m = thism.isShow = falsem.type = 'Point'm.drawMap(m.type)},polygon () {const m = thism.isShow = falsem.type = 'Polygon'this.drawMap(m.type)},edit (gemo) {const feature = new Feature({geometry: (new WKT()).readGeometryFromText(gemo)})// 保存到原始數據圖層this.vectorLayer.getSource().addFeature(feature)//this.map.view.setCenter(getCenter(feature.getGeometry().getExtent()));// let extent = vectorSource.getExtent()// this.view.fit(extent)},drawMap (type) {document.oncontextmenu = function () {return false}const m = thism.map.removeInteraction(this.draw)this.vectorLayer.getSource().clear()m.draw = new Draw({source: this.vectorLayer.getSource(),type: type,stopClick: true, // 繪制時禁用點擊事件style: this.getDrawingStyle()})m.draw.on('drawend', e => {// let coordinates = e.feature.getGeometry().getCoordinates();m.feature = e.featurevar a = new WKT()m.wkt = a.writeGeometry(m.feature.getGeometry())m.map.removeInteraction(m.draw)})this.map.addInteraction(m.draw)},getDrawingStyle () {return new Style({stroke: new Stroke({width: 2,color: [239, 176, 19, 1],lineDash: [1, 2, 3, 4, 5, 6]}),fill: new Fill({color: [239, 176, 19, 0.2]}),image: new Circle({// 點的顏色fill: new Fill({color: [246, 4, 4, 1]}),stroke: new Stroke({color: [239, 176, 19, 1]}),// 圓形半徑radius: 5})})},//點擊高亮樣式getHeightStyle(){var highlightStyle = new Style({fill: new Fill({color:"#890c08", //高亮區域填充顏色,可用rgba值}),stroke: new Stroke({color:"#0c0005", //高亮區域的邊界線顏色width:2}),image: new Circle({// 點的顏色fill: new Fill({color: "rgb(231,6,18,1)"}),stroke: new Stroke({color: "rgb(12,0,5,1)"}),// 圓形半徑radius: 10})});return highlightStyle;},//高亮樣式getlightStyle(){var lightStyle = new Style({stroke: new Stroke({width: 2,color: "3e84cf",lineDash: [1, 2, 3, 4, 5, 6]}),fill: new Fill({color: [239, 176, 19, 0.1]}),image: new Circle({// 點的顏色fill: new Fill({color: [246, 4, 4, 1]}),stroke: new Stroke({color: [239, 176, 19, 1]}),// 圓形半徑radius: 5})})return lightStyle;},clearDraw () {if(this.vectorLayer){this.vectorLayer.getSource().clear()}},getGeoHandle () {esb.$emit('MapHandle', { geometry: this.wkt })},close () {document.oncontextmenu = function () {return true}this.vectorLayer.getSource().clear()return esb.$emit('MapHandle', { geometry: this.wkt })},// 清除resets () {this.vectorLayer.getSource().clear()this.highlightLayer.getSource().clear()if (this.geoLayer) {console.log("clear geoLayer")this.map.removeLayer(this.geoLayer)this.geoLayer = null}},// 切換地圖changeMap(id){if(id=="YX"){this.yxLayer.setVisible(true);//console.log(111, this.$root.SHOWZJLAYER)this.zjLayer.setVisible(this.$root.SHOWZJLAYER==true);this.slLayer.setVisible(false);}else if(id=="SL") {this.yxLayer.setVisible(false);this.zjLayer.setVisible(false);this.slLayer.setVisible(true);}},// 添加GeoJOSNaddGeoJSON (url) {var m =this;m.clearGeoJSON()m.geoLayer = new VectorLayer({name: "tj",source: new VectorSource({features: new GeoJSON().readFeatures(url),}),style: function (feature) {var style = ""if (feature.get("style")?.fill.length > 0) {style = new Style({fill: new Fill({color: feature.get("style").fill || "rgb(0,0,0,0)"}),stroke: new Stroke({color: feature.get("style").stroke || "rgb(0,0,0,1)",width: 0.5,}),text: new Text({textAlign: "center",textBaseline: "middle",font: "bold 15px 微軟雅黑",text: `${feature.get("name")}`,fill: new Fill({color: "#8efff7"}),stroke: new Stroke({color: "#353535", width: 1}),}),});} else {style = m.getStyle(feature)}return style;}})m.geoLayer.setOpacity(0.7)// 添加GeoJSON到map上m.$nextTick(()=>{m.map.addLayer(this.geoLayer)})},getStyle(feature){return new Style({stroke: new Stroke({color: 'rgba(0, 0, 0, 1)',//通過要素拿到具體的值width: 0.5,opacity: 1}),fill: new Fill({color: 'rgba(255, 255, 0, 0.5)',// opacity: feature.opacity}),image: new Circle({// 點的顏色fill: new Fill({color: 'rgba(255, 255, 0, 0.5)',}),stroke: new Stroke({color: 'rgba(0, 0, 0, 1)',}),// 圓形半徑radius: 5})})},// 清除GeoJSONclearGeoJSON () {if (this.geoLayer) {this.map.removeLayer(this.geoLayer)this.geoLayer = null}},//添加高亮addHeighLight(feature){if(feature?.geometry?.type?.length>0){this.clearHeighLight()var fea = new GeoJSON().readFeature(feature, {featureProjection: "EPSG:4326" //規定要素以哪種坐標顯示});var style = this.getHeightStyle();fea.setStyle(style);this.highlightLayer.getSource().addFeature(fea)let extent = fea.getGeometry().getExtent();const view = this.map.getView()view.setCenter(extent)}},//清空高亮clearHeighLight(){if (this.highlightLayer) {this.highlightLayer.getSource().clear()}}} } </script><style scoped></style>調用
<template lang="pug">.homeview.map<Map :is-button="isButton" :area-show="areaShow" :geometrys="geometrys" :layerid="layerid" :geojsonurl="geojsonurl" :hightFeature="hightFeature"/>.bthimg(src='../assets/1.png' @click="changeMap(1)" v-if="lightmap == 2")img(src='../assets/2.png' @click="changeMap(2)" v-if="lightmap == 1")</template><script> import Map from '@/components/Map' import QG from '@/const/data/qg.json' import {list1,list2} from "@/views/Echars/index"; import {list} from "@/views/Echars/image"; import _ from 'lodash' import colors from "@/const/colors"; export default {name: 'HomeView',data() {return {areaShow: true,isButton: false,hightFeature:"",geometrys: [],treeshow: true,layerid: "TDT",geojsonurl:"",row:{},lightmap:1,whereCompany:''}},components:{Map},created() {},watch: {'$route.path':{immediate:true,handler(v) {if(v=='/Company'){this.whereCompany = "first"this.hightFeature =""this.geometrys=[]}else if(v=='/Image'){this.whereCompany = "Image"this.hightFeature =""this.geometrys=[]}else{this.whereCompany = ""this.hightFeature =""this.geometrys=[]this.geojsonurl="";}}}},methods:{// 切換地圖changeMap(data){var m =this;m.lightmap = data;if(m.lightmap==1){m.layerid="SL"}else {m.layerid="YX"}},//加載統計數據addGeoJson(url,data){var m =this;if(url=="QG"){m.geojsonurl="";var temp = JSON.parse(JSON.stringify(QG));temp.features?.forEach(item=>{var style={fill:"rgb(0,0,0,0.1)",opacity:"0.5",stroke:"rgb(0 0 0)"}var index = _.findIndex(data, el=>el.name==item.properties.name);let col =colors || []if(index>=0 && index <=col.length){style.fill=col[index];}item.properties.style=style;})m.geojsonurl=temp;}else{this.geojsonurl=url;}},//表格查詢,地圖加載點線面companyDataChange(e){//console.log(99,e);var m =this;m.geometrys=[]m.geojsonurl=""m.hightFeature=""var temp = JSON.parse(JSON.stringify(e));//企業結果if(temp.data?.length>0){let data = m.object2Geojson(temp.data);let data1=[];if(temp.data1?.length>0){data1 = m.object2Geojson(temp.data1)}var other = _.concat(data.features,data1.features);let geojson={"type":"FeatureCollection","features":[]}geojson.features=other;m.geojsonurl=geojson;}if(temp.nowdata?.length>0){let nowdata = m.object2Geojson(temp.nowdata);let nowdata1=[];if(temp.nowdata1?.length>0){nowdata1= m.object2Geojson(temp.nowdata1)}var other1 = _.concat(nowdata.features,nowdata1.features);m.geometrys=other1;}//影像查詢結果if(temp.data3?.length>0){let geojson={"type":"FeatureCollection","features":[]}geojson.features=temp.data3m.geojsonurl=geojson;}if(temp.nowdata3?.length>0){m.geometrys=temp.nowdata3;}},//json轉geojsonobject2Geojson(data){var featureCollection = {"type": "FeatureCollection"};var features = new Array();for (let i = 0; i < data.length; i++) {var feature = {"type": "Feature"};feature.properties = data[i];var geometry = {"type": "Point"};geometry.coordinates = [data[i].lon, data[i].lat];feature.geometry = geometry;features.push(feature);}featureCollection.features = features;return featureCollection;}} } </script><style lang=less rel="stylesheet/less" scoped> .homeview{height: calc(100vh - 74px);display: flex;.map{flex:1;position: relative;>.bth{position: absolute;right: 12px;bottom:12px;z-index: 999;border:1px #265df7 solid;width: 86px;height: 60px;overflow: hidden;img:first-child{cursor: pointer;}}}.Search,.company{width: 450px;margin-left: 2px;overflow: hidden;height: 100%;} } </style>七、參考網址
參考資料:
openlayers官網:https://openlayers.org/
geojson下載網站:https://datav.aliyun.com/portal/school/atlas/area_selector
地圖坐標拾取網站:https://api.map.baidu.com/lbsapi/getpoint/index.html
?
總結
以上是生活随笔為你收集整理的vue+ol实现 ol 地图加载geojson的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【强推】李宏毅老师2021深度学习课程学
- 下一篇: 网页调用QQ聊天