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