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