实现区域高亮选择
1.初始化地图
主要通过geojson数据实现边界显示,没有的话可以在这里下载,不过只有区级数据,街道数据自己想办法啦
参考
推荐一个免费下载省-市-区县行政区Shp数据的方法
index.js
import OlMap from '@/components/OlMap/OlMap'; //引入地图的一些方法
import { unByKey } from 'ol/Observable';
let mapListener;
componentWillUnmount() {
this.initial()
}
initial() {
this.OlMapView.initMap(id, lng, lat, zoom);//自定义地图id、默认中心点、层级
if (mapListener) {
unByKey(mapListener);
}
mapListener = this.OlMapView.state.selector.on('select', e => {
this.handleSelect(e.selected);
});
this.OlMapView.addLayerQX_geojson();//通过geojson数据加载边界图层
}
handleSelect(features) {
if (features.length > 0) {
//获取属性
let featureInfo = features[0].getProperties();
console.log('选中的点位信息:', featureInfo);
this.OlMapView.addArea(featureInfo);//获取点击选择的区域,判断高亮显示还是取消
}
}
<OlMap
id={'OlMapView'}
ref={node => (this.OlMapView = node)}
{...this.props}
onChangeMapState={this.onChangeMapState.bind(this)}
areaList={areaList}
/>
OlMap.js
let baseMapUrl =baseMapUrl;
let map;
let layers = [];
let areaLayerQX = null;//区域边界图层
let AreaFeatures = null;
let streetLayer = null;//街道边界图层
let areaInfo = null;
let streetInfo = null;
this.state = {
selector: selector,
loading: false,
streetLayerVisible: false,
streetList: [],//保存所选街道信息
};
initMap(id, lng, lat, zoom) {
const _this = this;
centerPoint = lng + '' + lat;
map = new Map({
target: id,
view: new View({
projection: 'EPSG:4326', //使用这个坐标系
center: lng && lat ? [lng, lat] : [104.0576, 30.6632], //地图中心点位置
zoom: zoom ? zoom : 10,
minZoom: 10,
maxZoom: 22,
}),
});
this.initLayers();
map.setLayers(layers);
map.addInteraction(this.state.selector); //map加载该控件,默认是激活可用的
//鼠标样式
map.on('pointermove', e => {
if (_this.props.drawCircle == true && circleArr.length > 0) {
_this.removeLabel();
let radius = getDistance(circleArr[0], e.coordinate);
console.log(radius, '圆半径');
const labelElement = document.createElement('div');
labelElement.className = `${style.highlight_con}`;
labelElement.innerHTML = `
<div class=${style.highlight}>半径:${Math.trunc(radius)}米
</div>`;
let overlay = new Overlay({
element: labelElement,
position: e.coordinate,
positioning: 'center-center',
stopEvent: false,
});
highlight_overlay.push(overlay);
map.addOverlay(overlay);
}
let pixel = map.getEventPixel(e.originalEvent);
let feature = map.forEachFeatureAtPixel(pixel, function(feature) {
return feature;
});
if (feature) {
map.getTargetElement().style.cursor = 'pointer';
} else {
map.getTargetElement().style.cursor = 'auto';
}
});
map.on('moveend', function(e) {
var zoom = map.getView().getZoom(); //获取当前地图的缩放级别
console.log(zoom, 'zoom');
if (zoom > 11) {//地图层级超过11级后显示街道图层,隐藏区域图层,反之交换显示
_this.setState({
streetLayerVisible: true,
});
streetLayer.setVisible(true);
areaLayerQX.setVisible(false);
} else {
streetLayer.setVisible(false);
areaLayerQX.setVisible(true);
}
_this.props.onChangeAreaNoEquip();
let center = _this.getMapCenter();
centerPoint = center[0] + '' + center[1];
});
map.on('click', event => {
console.log('点击坐标=>', event.coordinate, event);
});
}
// 添加底图
initLayers() {
let url = `${baseMapUrl}`; // 彩色系
let resolutions = [
0.7031250000000002,
0.3515625000000001,
0.17578125000000006,
0.08789062500000003,
0.043945312500000014,
0.021972656250000007,
0.010986328125000003,
0.005493164062500002,
0.002746582031250001,
0.0013732910156250004,
6.866455078125002e-4,
3.433227539062501e-4,
1.7166137695312505e-4,
8.583068847656253e-5,
4.2915344238281264e-5,
2.1457672119140632e-5,
1.0728836059570316e-5,
5.364418029785158e-6,
2.682209014892579e-6,
1.3411045074462895e-6,
];
let matrixIds = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
let origin = [-180, 90];
let tileGrid = new WMTSTileGrid({
origin: origin, // 原点(左上角)
resolutions: resolutions, // 分辨率数组
matrixIds: matrixIds, // 矩阵标识列表,与地图级数保持一致
});
// 基础底图
let baseLayer = new TileLayer({
source: new XYZ({
projection: 'EPSG:4326',
// tileGrid: tileGrid, // 蓝色、白色底图需加此切片方案
url: ``,
wrapX: true, // 是否水平包裹地图
}),
});
layers.push(baseLayer);
const vectorSourceArea = new VectorSource();//区域图层
areaLayerQX = new VectorLayer({
source: vectorSourceArea,
});
layers.push(areaLayerQX);
const vectorSourceStreet = new VectorSource();//街道图层
streetLayer = new VectorLayer({
visible: this.state.streetLayerVisible,
source: vectorSourceStreet,
});
layers.push(streetLayer);
}
2.添加区域边界
OLmap.js
addLayerQX_geojson(name) {
let _this = this;
this.setState({
loading: true,
});
if (QXFeatures == null) {
const json = require('./json/shanghai.json');
let featuresQX = new GeoJSON().readFeatures(json);
QXFeatures = featuresQX;
this.setState({
loading: false,
});
_this.addRegionQX(QXFeatures);
} else {
_this.addRegionQX(QXFeatures);
this.setState({
loading: false,
});
}
}
addRegionQX(QXFeatures) {
let _this = this;
regionLayerQX.getSource().addFeatures(QXFeatures);
let features = regionLayerQX.getSource().getFeatures();
for (let j = 0; j < features.length; j++) {
let properties = features[j].getProperties();
features[j].setStyle(
new Style({
// 多边形填充颜色
fill: new Fill({
color: 'rgba(115,251,253, 0)',
}),
// 多边形边框颜色
stroke: new Stroke({
color: 'rgba(115,251,253, 0)',
width: 2,
}),
text: new Text({
//位置
textAlign: 'center',
//基准线
textBaseline: 'bottom',
fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
//文字样式
font: 'normal 24px Alibaba-PuHuiTi-M',
// font: 'normal 18px 微软雅黑',
//文本内容
text: properties.COUTRICT,
anchorOrigin: 'bottom-right',
offsetY: 0,
}),
})
);
}
}
3.点击区域高亮显示或隐藏
index.js
handleSelect(features) {
if (features.length > 0) {
//获取属性
let featureInfo = features[0].getProperties();
console.log('选中的点位信息:', featureInfo);
this.OlMapView.addArea(featureInfo);//获取点击选择的区域,判断高亮显示还是取消
}
}
选择区域的同时加载街道边界,取消区域择清除街道边界
放大层级后会显示街道边界,保存选择街道信息到streetList中,然后筛选出相应的坐标数据,渲染到地图上
OLmap.js
addArea(featureInfo) {
let _this = this;
let json = undefined;
let featuresQX = undefined;
json = require('./json/shanghai.json');
let geojson = {
type: 'FeatureCollection',
features: [],
};
json.features.map(item => {//查找所选区域信息
if (item.properties.COUTRICT == featureInfo.COUTRICT) {
geojson.features.push({
type: 'Feature',
id: featureInfo.ID,
geometry: {
type: 'Polygon',
coordinates: item.geometry.coordinates,
},
});
featuresQX = new GeoJSON().readFeatures(item);
}
});
if (AreaFeatures == null) {//初次点击
AreaFeatures = featuresQX;
areaInfo = featureInfo;
_this.addRegionHighlight(AreaFeatures);
_this.addStreet(featureInfo);
} else {
if (
areaInfo &&
(areaInfo.COUTRICT == featureInfo.COUTRICT )
) {//判断当前点击的是否为已经选择过的区域
if (featureInfo.town) {
streetLayer.getSource().clear();
_this.setState({
loading: false,
});
let streetList = this.state.streetList;
let json = [];
if (streetList.indexOf(featureInfo.town) > -1) {//如点击的是已选择的街道,删除
streetList = streetList.filter(item => item != featureInfo.town);
} else {//反之插入
streetList.push(featureInfo.town);
}
json = streetInfo.features.filter(item => streetList.includes(item.attributes.town));
let geojson = {
type: 'FeatureCollection',
features: [],
};
this.setState({
streetList: streetList,
});
for (let i = 0; i < streetInfo.features.length; i++) {
geojson.features.push({
type: 'Feature',
id: i,
geometry: {
type: 'Polygon',
coordinates: streetInfo.features[i].geometry.rings,
},
properties: { ...streetInfo.features[i].attributes },
});
}
let streetFeatures = new GeoJSON().readFeatures(geojson);
streetLayer.getSource().addFeatures(streetFeatures);//渲染高亮显示的街道
let features = streetLayer.getSource().getFeatures();
for (let j = 0; j < features.length; j++) {
let properties = features[j].getProperties();
if(streetList.includes(properties.town)){
features[j].setStyle(
new Style({
// 多边形填充颜色
fill: new Fill({
color: 'rgba(47, 167, 169, 0.20)',
}),
// 多边形边框颜色
stroke: new Stroke({
color: 'rgba(47, 155, 169, 1)',
width: 2,
}),
text: new Text({
//位置
textAlign: 'center',
//基准线
textBaseline: 'bottom',
fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
//文字样式
font: 'normal 24px Alibaba-PuHuiTi-M',
//文本内容
text: properties.town,
anchorOrigin: 'bottom-right',
offsetY: 0,
}),
})
);
}else{
features[j].setStyle(
new Style({
// 多边形填充颜色
fill: new Fill({
color: 'rgba(47, 167, 169, 0)',
}),
// 多边形边框颜色
stroke: new Stroke({
color: 'rgba(47, 155, 169, 1)',
width: 2,
}),
text: new Text({
//位置
textAlign: 'center',
//基准线
textBaseline: 'bottom',
fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
//文字样式
font: 'normal 24px Alibaba-PuHuiTi-M',
// font: 'normal 18px 微软雅黑',
//文本内容
text: properties.town,
anchorOrigin: 'bottom-right',
offsetY: 0,
}),
})
);
}
}
} else {//点击的是已选择的区域,取消高亮,同时清除街道图层
AreaFeatures = null;
areaInfo = null;
areaLayerQX.getSource().clear();
streetLayer.getSource().clear();
this.setState({
streetList:[]
})
}
} else {
areaLayerQX.getSource().clear();
AreaFeatures = featuresQX;
areaInfo = featureInfo;
_this.addRegionHighlight(AreaFeatures);
_this.addStreet(featureInfo);
}
}
}
addRegionHighlight(QXFeatures) {//高亮区域图层
let _this = this;
if (QXFeatures) {
areaLayerQX.getSource().addFeatures(QXFeatures);
let features = areaLayerQX.getSource().getFeatures();
for (let j = 0; j < features.length; j++) {
let properties = features[j].getProperties();
features[j].setStyle(
new Style({
// 多边形填充颜色
fill: new Fill({
color: 'rgba(47, 167, 169, 0.20)',
}),
// 多边形边框颜色
stroke: new Stroke({
color: 'rgba(47, 155, 169, 1)',
width: 2,
}),
text: new Text({
//位置
textAlign: 'center',
//基准线
textBaseline: 'bottom',
fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
//文字样式
font: 'normal 24px Alibaba-PuHuiTi-M',
// font: 'normal 18px 微软雅黑',
//文本内容
text: properties.COUTRICT,
anchorOrigin: 'bottom-right',
offsetY: 0,
}),
})
);
}
}
}
addStreet(featureInfo) {//渲染街道底图
let _this = this;
_this.setState({
loading: true,
});
streetLayer.getSource().clear();
let regionName = featureInfo.COUTRICT;
const serviceUrl = serviceUrl ;//获取街道边界数据
fetch(queryUrl, {
headers: {},
})
.then(response => {
return response.json();
})
.then(json => {
_this.setState({
loading: false,
});
streetInfo = json;
let geojson = {
type: 'FeatureCollection',
features: [],
};
let streetList = [];
for (let i = 0; i < json.features.length; i++) {
streetList.push(json.features[i].attributes.town);
geojson.features.push({
type: 'Feature',
id: i,
geometry: {
type: 'Polygon',
coordinates: json.features[i].geometry.rings,
},
properties: {
...json.features[i].attributes,
}),
},
});
}
_this.setState({
streetList: streetList,
});
let streetFeatures = new GeoJSON().readFeatures(geojson);
streetLayer.getSource().addFeatures(streetFeatures);
let features = streetLayer.getSource().getFeatures();
for (let j = 0; j < features.length; j++) {
let properties = features[j].getProperties();
features[j].setStyle(
new Style({
// 多边形填充颜色
fill: new Fill({
color: 'rgba(47, 167, 169, 0.20)',
}),
// 多边形边框颜色
stroke: new Stroke({
color: 'rgba(47, 155, 169, 1)',
width: 2,
}),
text: new Text({
//位置
textAlign: 'center',
//基准线
textBaseline: 'bottom',
fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
//文字样式
font: 'normal 24px Alibaba-PuHuiTi-M',
// font: 'normal 18px 微软雅黑',
//文本内容
text: properties.town,
anchorOrigin: 'bottom-right',
offsetY: 0,
}),
})
);
}
});
}