本文介绍了如何使用OpenLayers在区县地图上加载不同颜色的坐标点,并通过点击展示详细信息。之前在12章节我们只是利用了一种办法实现了效果,现在我们通过另一种办法也可以实现相同效果。
首先设置地图视图和天地图底图,然后创建三种颜色的坐标点图层(黄、红、绿),分别用不同图标表示。绿色坐标点还包含名称、省市区等属性信息。通过添加点击事件监听,当用户点击绿色点时,会弹出信息框显示该点的详细属性数据。实现过程包括:创建矢量图层、设置点样式、绑定点击事件、处理特征属性等。通过forEachFeatureAtPixel方法获取点击位置的特征信息;使用Overlay实现弹窗功能,动态显示所选点的详细信息。
一、解释
let map=null;
let popup=null;
定义两个全局变量
const [name,setname]=useState('')
const [prov,setprov]=useState('')
const [city,setcity]=useState('')
const [distr,setdistr]=useState('')
定义state数据,用来存储相关信息
let view=new View({center:fromLonLat([123.464679, 41.677586]),zoom:9,})
定义视图和中心
let ditulayer=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"})})
let biaojilayer=new TileLayer({source:new XYZ({url :"http://t3.tianditu.com/DataServer?T=cva_w&tk=faf4cf166d31edcaba5de523eae8084f&x={x}&y={y}&l={z}"})})
定义底图和标注图层
let vectorlayer=new VectorLayer({
source:new VectorSource({url:"https://geo.datav.aliyun.com/areas_v3/bound/210100.json",format:new GeoJSON()}),
style:new Style({
fill:new Fill({
color:"rgba(0,96,255,0.2)"
}),
stroke:new Stroke({
color:'#0060ff',
width:3
})
})
})
定义矢量图层,显示一定范围,并给出背景色和边框这两种效果
let yellowsource=new VectorSource({})
let yellowlayer=new VectorLayer({source:yellowsource})
let yellowpoints=[fromLonLat([123.464679, 41.677586]),fromLonLat([123.33, 41.67]),fromLonLat([122.82283, 41.99203899])]
yellowpoints.forEach(function(coords){
let yellowfeature = new Feature({
geometry: new Point(coords),
});
yellowfeature.setStyle(
new Style({
image:new Icon({
src:yellow,
})
})
)
yellowsource.addFeature(yellowfeature);
})
显示黄色箭头
let redsource=new VectorSource({})
let redlayer=new VectorLayer({source:redsource})
let redpoints=[fromLonLat([123.249151,41.748329]),fromLonLat([123.584281, 41.913100])]
redpoints.forEach(function(coords){
let redfeature = new Feature({
geometry: new Point(coords),
});
redfeature.setStyle(
new Style({
image:new Icon({
src:red,
})
})
)
redsource.addFeature(redfeature);
})
显示红色箭头
const greenList=[
{lonlat:[123.184471, 42.342171],name:"丁家房镇",prov:"辽宁",city:"沈阳",distr:"法库"},
{lonlat:[123.370625,41.852098],name:"梁山镇",prov:"辽宁",city:"沈阳",distr:"新民"},
{lonlat:[123.370625,41.852098],name:"梁山镇",prov:"辽宁",city:"沈阳",distr:"新民"},
]
const greensource=new VectorSource({})
const greenlayer=new VectorLayer({source:greensource})
greenList.forEach(function(item){
let greenfeature = new Feature({
geometry: new Point(fromLonLat(item.lonlat)),
name: item.name,
});
greenfeature.setStyle(
new Style({
image:new Icon({
src:green,
})
})
)
greensource.addFeature(greenfeature);
})
显示绿色箭头
map.on('singleclick', function(evt) {
map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
if (layer === greenlayer) {
let feature2=feature;
console.log(feature2);
let selectname=feature2.get("name");
let geometry=feature2.getGeometry().getCoordinates()
greenList.map((item,index)=>{
if(item.name==selectname){
setname(item.name);
setcity(item.city)
setprov(item.prov)
setdistr(item.distr)
}
})
popup.setPosition(geometry);
map.addOverlay(popup);
}else{
console.log('Clicked on the tile layer');
}
});
});
map点击事件获取相关数据
二、完整代码
import { useState ,useEffect} from 'react';
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
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 {fromLonLat} from 'ol/proj';
import './System.css'
import 'ol/ol.css';
import yellow from '../../assets/yellow.png';
import red from '../../assets/red.png';
import green from '../../assets/green.png';
import close from '../../assets/close.png';
let map=null;
let popup=null;
function System() {
const [name,setname]=useState('')
const [prov,setprov]=useState('')
const [city,setcity]=useState('')
const [distr,setdistr]=useState('')
let view=new View({center:fromLonLat([123.464679, 41.677586]),zoom:9,})
let ditulayer=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"})})
let biaojilayer=new TileLayer({source:new XYZ({url :"http://t3.tianditu.com/DataServer?T=cva_w&tk=faf4cf166d31edcaba5de523eae8084f&x={x}&y={y}&l={z}"})})
let vectorlayer=new VectorLayer({
source:new VectorSource({url:"https://geo.datav.aliyun.com/areas_v3/bound/210100.json",format:new GeoJSON()}),
style:new Style({
fill:new Fill({
color:"rgba(0,96,255,0.2)"
}),
stroke:new Stroke({
color:'#0060ff',
width:3
})
})
})
let yellowsource=new VectorSource({})
let yellowlayer=new VectorLayer({source:yellowsource})
let yellowpoints=[fromLonLat([123.464679, 41.677586]),fromLonLat([123.33, 41.67]),fromLonLat([122.82283, 41.99203899])]
yellowpoints.forEach(function(coords){
let yellowfeature = new Feature({
geometry: new Point(coords),
});
yellowfeature.setStyle(
new Style({
image:new Icon({
src:yellow,
})
})
)
yellowsource.addFeature(yellowfeature);
})
let redsource=new VectorSource({})
let redlayer=new VectorLayer({source:redsource})
let redpoints=[fromLonLat([123.249151,41.748329]),fromLonLat([123.584281, 41.913100])]
redpoints.forEach(function(coords){
let redfeature = new Feature({
geometry: new Point(coords),
});
redfeature.setStyle(
new Style({
image:new Icon({
src:red,
})
})
)
redsource.addFeature(redfeature);
})
const greenList=[
{lonlat:[123.184471, 42.342171],name:"丁家房镇",prov:"辽宁",city:"沈阳",distr:"法库"},
{lonlat:[123.370625,41.852098],name:"梁山镇",prov:"辽宁",city:"沈阳",distr:"新民"},
{lonlat:[123.370625,41.852098],name:"梁山镇",prov:"辽宁",city:"沈阳",distr:"新民"},
]
const greensource=new VectorSource({})
const greenlayer=new VectorLayer({source:greensource})
greenList.forEach(function(item){
let greenfeature = new Feature({
geometry: new Point(fromLonLat(item.lonlat)),
name: item.name,
});
greenfeature.setStyle(
new Style({
image:new Icon({
src:green,
})
})
)
greensource.addFeature(greenfeature);
})
useEffect(()=>{
map=new Map({
target:"mapp",
view:view,
layers:[
ditulayer,
biaojilayer,
vectorlayer,
yellowlayer,
redlayer,
greenlayer
]
})
popup=new Overlay({
element:document.getElementById("popup"),
})
map.addOverlay(popup)
map.on('singleclick', function(evt) {
map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
if (layer === greenlayer) {
let feature2=feature;
console.log(feature2);
let selectname=feature2.get("name");
let geometry=feature2.getGeometry().getCoordinates()
greenList.map((item,index)=>{
if(item.name==selectname){
setname(item.name);
setcity(item.city)
setprov(item.prov)
setdistr(item.distr)
}
})
popup.setPosition(geometry);
map.addOverlay(popup);
}else{
console.log('Clicked on the tile layer');
}
});
});
},[])
function closeTag(){
popup.setPosition(undefined);
}
return (
<>
<div id="mapp" style={{width: "100%",height: "97vh"}}>
<div id="popup">
<div className="row_title">
<span>信息如下:</span>
<img className="row_title_img" src={close} onClick={closeTag}/>
</div>
<div className="row_content">
<div>名称:{name}</div>
<div>省份:{prov}</div>
<div>城市:{city}</div>
<div>区县:{distr}</div>
</div>
</div>
</div>
</>
)
}
export default System