OpenLayers(简称ol)是一个开源的WebGIS前端开发库,基于JavaScript实现,主要用于在网页中嵌入动态二维地图。
官方网站: https://openlayers.org
中文官网: https://openlayers.vip
大家可以去参考学习一些api等内容
下面我们做一个类似效果,首先我只要某个区域,并将这个区域用颜色来覆盖,用边框来画出来。并在这个区域内加一些我自己的坐标点,这些坐标点根据类型不同使用不同颜色的图片来表示,点击这些点,弹出一个popup列表框,显示相关数据信息。
全部代码如下:
一、引入相关组件:(里面几个图片用来显示不同的点)
import React,{ useState ,useEffect,useRef} from 'react';
import { Button } from 'antd';
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
import {fromLonLat} from 'ol/proj';
import XYZ from 'ol/source/XYZ.js';
import VectorLayer from 'ol/layer/Vector.js';
import VectorSource from 'ol/source/Vector.js';
import GeoJSON from 'ol/format/GeoJSON.js';
import Style from 'ol/style/Style.js';
import Fill from 'ol/style/Fill.js';
import Stroke from 'ol/style/Stroke.js';
import Icon from 'ol/style/Icon.js';
import Feature from 'ol/Feature.js';
import Polygon from 'ol/geom/Polygon.js';
import Point from 'ol/geom/Point.js';
import Overlay from 'ol/Overlay.js';
import 'ol/ol.css';
import yellow from '../../assets/yellow.png';
import blue from '../../assets/blue.png';
import green from '../../assets/green.png';
import close from '../../assets/map-close.png';
第二步、创建所需视图和图层
view:是视图,也就是我们看到的整个区域。可以设置中心坐标,坐标系,缩放等内容。
layers是图层,其中layer一个是底图(类似地图大致轮廓)、layer2一个是标注(带有地理位置名称)、VectorLayer2是我选中的所在区域,因为我想让这个区域在地图上显示不一样,比如让某区域加个颜色,加个边框等等。
const view=new View({center:fromLonLat([122.356879,41.734601]),zoom:10,minZoom:8,maxZoom:12})const layer=new TileLayer({ source: new XYZ({url:"http://t5.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=528881a2c3d647268c04ab43dc46bd51"})})const layer2=new TileLayer({ source: new XYZ({url:"http://t3.tianditu.com/DataServer?T=cva_w&tk=faf4cf166d31edcaba5de523eae8084f&x={x}&y={y}&l={z}"})})const VectorSource2=new VectorSource({ url:"https://geo.datav.aliyun.com/areas_v3/bound/210726.json",format:new GeoJSON()})const VectorLayer2=new VectorLayer({source:VectorSource2,style:new Style({fill:new Fill({color:"rgba(0,96,255,0.2)"}),stroke:new Stroke({color:'#0060ff',width:3})}),})
三、自定义坐标点,可以看到在我这个地图中,有些多黄色蓝色绿色的坐标点,这些坐标点是我自定义的,我想点击这些坐标点提示这些坐标点内的数据。
const yellowsource=new VectorSource({})const yellowlayer=new VectorLayer({source:yellowsource})const yellowpoints=[fromLonLat([122.486629,41.570355]),fromLonLat([122.498091,41.617429]),fromLonLat([121.992578,41.906638]),fromLonLat([122.550649,41.678931]),fromLonLat([121.936423,41.875015])]yellowpoints.forEach(function(coords){let yellowfeature = new Feature({geometry: new Point(coords),});yellowfeature.setStyle(new Style({image:new Icon({src:yellow,})}))yellowsource.addFeature(yellowfeature); })const bluesource=new VectorSource({})const bluelayer=new VectorLayer({source:bluesource})const bluepoints=[fromLonLat([122.561534,41.783343]),fromLonLat([122.459847,41.849685]),fromLonLat([121.846006,41.83962]),fromLonLat([122.457756,41.856836]),fromLonLat([122.132125,42.002747])]bluepoints.forEach(function(coords){let bluefeature = new Feature({geometry: new Point(coords),});bluefeature.setStyle(new Style({image:new Icon({src:blue,})}))bluesource.addFeature(bluefeature); })const greensource=new VectorSource({})const greenlayer=new VectorLayer({source:greensource})const greenpoints=[fromLonLat([122.428214,42.093392]),fromLonLat([122.06593,41.971059]),fromLonLat([122.039448,41.644037]),fromLonLat([122.194422,42.033781]),fromLonLat([122.46685,42.04159])]greenpoints.forEach(function(coords){let greenfeature = new Feature({geometry: new Point(coords),});greenfeature.setStyle(new Style({image:new Icon({src:green,})}))greensource.addFeature(greenfeature); })
四、将数据绑定到地图中,并在地图里面添加点击事件,并且只有限制,只有点击到我自定义的坐标上时候,才显示相关内容。
useEffect(()=>{map=new Map({target:"map",view:view,layers:[layer,layer2,VectorLayer2,yellowlayer,bluelayer,greenlayer]})popup=new Overlay({element:document.getElementById("popup"),})map.addOverlay(popup)map.on("click",function(e){let pixel=e.pixel;let features=map.getFeaturesAtPixel(pixel);if(features.length>=2){var geometry = features[0].getGeometry().getCoordinates();var geometry2 = features[1].getGeometry().getCoordinates();popup.setPosition(geometry);map.addOverlay(popup);} })},[])
五、点击关闭按钮隐藏卡片
function _closeOverlay(){console.log('删除overlay')popup.setPosition(undefined);// map.removeOverlay(popup);}
六、全部代码如下
import React,{ useState ,useEffect,useRef} from 'react';
import { Button } from 'antd';
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
import {fromLonLat} from 'ol/proj';
import XYZ from 'ol/source/XYZ.js';
import VectorLayer from 'ol/layer/Vector.js';
import VectorSource from 'ol/source/Vector.js';
import GeoJSON from 'ol/format/GeoJSON.js';
import Style from 'ol/style/Style.js';
import Fill from 'ol/style/Fill.js';
import Stroke from 'ol/style/Stroke.js';
import Icon from 'ol/style/Icon.js';
import Feature from 'ol/Feature.js';
import Polygon from 'ol/geom/Polygon.js';
import Point from 'ol/geom/Point.js';
import Overlay from 'ol/Overlay.js';
import 'ol/ol.css';
import yellow from '../../assets/yellow.png';
import blue from '../../assets/blue.png';
import green from '../../assets/green.png';
import close from '../../assets/map-close.png';let map=null;
let popup=null;
function GisMapView() {const [count, setCount] = useState(0)const [center,setCenter]=useState(0)const mapDiv = useRef(null);const view=new View({center:fromLonLat([122.356879,41.734601]),zoom:10,minZoom:8,maxZoom:12})const layer=new TileLayer({ source: new XYZ({url:"http://t5.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=528881a2c3d647268c04ab43dc46bd51"})})const layer2=new TileLayer({ source: new XYZ({url:"http://t3.tianditu.com/DataServer?T=cva_w&tk=faf4cf166d31edcaba5de523eae8084f&x={x}&y={y}&l={z}"})})const VectorSource2=new VectorSource({ url:"https://geo.datav.aliyun.com/areas_v3/bound/210726.json",format:new GeoJSON()})const VectorLayer2=new VectorLayer({source:VectorSource2,style:new Style({fill:new Fill({color:"rgba(0,96,255,0.2)"}),stroke:new Stroke({color:'#0060ff',width:3})}),})const yellowsource=new VectorSource({})const yellowlayer=new VectorLayer({source:yellowsource})const yellowpoints=[fromLonLat([122.486629,41.570355]),fromLonLat([122.498091,41.617429]),fromLonLat([121.992578,41.906638]),fromLonLat([122.550649,41.678931]),fromLonLat([121.936423,41.875015])]yellowpoints.forEach(function(coords){let yellowfeature = new Feature({geometry: new Point(coords),});yellowfeature.setStyle(new Style({image:new Icon({src:yellow,})}))yellowsource.addFeature(yellowfeature); })const bluesource=new VectorSource({})const bluelayer=new VectorLayer({source:bluesource})const bluepoints=[fromLonLat([122.561534,41.783343]),fromLonLat([122.459847,41.849685]),fromLonLat([121.846006,41.83962]),fromLonLat([122.457756,41.856836]),fromLonLat([122.132125,42.002747])]bluepoints.forEach(function(coords){let bluefeature = new Feature({geometry: new Point(coords),});bluefeature.setStyle(new Style({image:new Icon({src:blue,})}))bluesource.addFeature(bluefeature); })const greensource=new VectorSource({})const greenlayer=new VectorLayer({source:greensource})const greenpoints=[fromLonLat([122.428214,42.093392]),fromLonLat([122.06593,41.971059]),fromLonLat([122.039448,41.644037]),fromLonLat([122.194422,42.033781]),fromLonLat([122.46685,42.04159])]greenpoints.forEach(function(coords){let greenfeature = new Feature({geometry: new Point(coords),});greenfeature.setStyle(new Style({image:new Icon({src:green,})}))greensource.addFeature(greenfeature); })useEffect(()=>{map=new Map({target:"map",view:view,layers:[layer,layer2,VectorLayer2,yellowlayer,bluelayer,greenlayer]})popup=new Overlay({element:document.getElementById("popup"),})map.addOverlay(popup)map.on("click",function(e){let pixel=e.pixel;let features=map.getFeaturesAtPixel(pixel);if(features.length>=2){var geometry = features[0].getGeometry().getCoordinates();var geometry2 = features[1].getGeometry().getCoordinates();popup.setPosition(geometry);map.addOverlay(popup);} })},[])function _closeOverlay(){console.log('删除overlay')popup.setPosition(undefined);// map.removeOverlay(popup);}return (<><div id="map" ref={mapDiv} style={{width: "100%",height: "98vh"}}><div id="popup"><div className="popup_header"><div className="popup_header_left"><img className="popup_header_left_img" src={green}/><div className="popup_header_left_name">红光二</div></div><img id="popup-closer" className="popup_header_rigth" src={close} onClick={_closeOverlay}/></div><div className="popup_content"><div className="popup_content_item"><div className="popup_content_item_name">液位</div><div className="popup_content_item_content"><div className="popup_content_item_content_count">1.3</div><div className="popup_content_item_content_unit">m</div></div></div><div className="popup_content_item"><div className="popup_content_item_name">排水流量</div><div className="popup_content_item_content"><div className="popup_content_item_content_count">1.3</div><div className="popup_content_item_content_unit">m</div></div></div><div className="popup_content_item"><div className="popup_content_item_name">排水站状态</div><div className="popup_content_item_content"><div className="popup_content_item_content_states">正常</div></div></div><div className="popup_content_item"><div className="popup_content_item_name">采集时间</div><div className="popup_content_item_content"><div className="popup_content_item_content_unit">05-01 10:00:00</div></div></div></div></div><div className="map_side_menu"><div className="map_side_menu_item"><img className="map_side_menu_item_img" src={green}/><div className="map_side_menu_item_content"><div className="map_side_menu_item_content_name">排水站</div><div className="map_side_menu_item_content_count">50个</div></div></div><div className="map_side_menu_item"><img className="map_side_menu_item_img" src={yellow}/><div className="map_side_menu_item_content"><div className="map_side_menu_item_content_name">液位计</div><div className="map_side_menu_item_content_count">50个</div></div></div><div className="map_side_menu_item"><img className="map_side_menu_item_img" src={blue}/><div className="map_side_menu_item_content"><div className="map_side_menu_item_content_name">视频监控</div><div className="map_side_menu_item_content_count">50个</div></div></div></div></div></>)
}export default GisMapView