openlayers +GeoJSON 给不同的行政区显示不同的
1、效果
普通效果
image.png
选中效果
image.png
2,初始化地图
this.view = new View({
projection: 'EPSG:4326',
center: options.center || [113.625351, 34.746303], // 郑州
zoom: options.zoom || 12
})
this.map = new Map({
target: this.$refs.map,
layers: [
new TileLayer({
title: '网格',
source: new XYZ({
visible: true,
wrapX: true,
url: '地图影像'
})
})
],
view: this.view
})
3、添加GeoJSON数据并给不同的行政区域添加颜色
···
createStyle(feature,{
textAlign="center",
justify="center",
areaFillColor='rgba(47, 209, 117, 0.3)',
areaStrokeColor='#2FD175',
textFillCOlor='#2FD175',
textStrokeColor='#fff'}) {
return new Style({
fill:new Fill({
color:feature.get('name')==='中原区'?'rgba(255,0,0,0.3)':areaFillColor
}),
stroke:new Stroke({
color:feature.get('name')==='中原区'?'red':areaStrokeColor,
width:2
}),
text: new Text({
font: '16px PingFang SC',
textAlign,
justify,
text:feature.get('name'),
fill: new Fill({
color: feature.get('name')==='中原区'?'red':textFillCOlor,
}),
stroke:new Stroke({
color:textStrokeColor,
width:2
}),
}),
});
},
const source = new VectorSource({
url: 'https://geo.datav.aliyun.com/areas_v3/bound/410100_full.json',
format: new GeoJSON()
})
const vectorLayer = new VectorLayer({
source: source,
style:this.createStyle
})
this.map.addLayer(vectorLayer)
···
5、给行政区域添加点击事件
···
handlePolygon(){
const polygonClick = new Select({
style: this.setSelectStyle,
});
this.map.addInteraction(polygonClick);
polygonClick.on('select',(e)=>{
// console.log('点击',e.selected,e,e.target)
this.$emit('click',e.selected,e)
})
},
setSelectStyle(feature,{
areaFillColor='rgba(47, 209, 117, 0.7)',
areaStrokeColor='#2FD175',
textAlign="center",
justify="center",
textFillCOlor='#2FD175',
textStrokeColor='#fff'}) {
let selected = new Style({
fill: new Fill({
color: areaFillColor,
}),
stroke: new Stroke({
color: areaStrokeColor,
width: 2,
}),
text: new Text({
font: '16px PingFang SC',
textAlign,
justify,
text:feature.get('name'),
fill: new Fill({
color: feature.get('name')==='中原区'?'red':textFillCOlor,
}),
stroke:new Stroke({
color:textStrokeColor,
width:2
}),
}),
});
return selected;
},
···
完整代码
<template>
<div class="page-container">
<div class="map-container" ref="map"></div>
</div>
</template>
<script>
import 'ol/ol.css'
import { Map, View, Feature } from 'ol'
// import {Projection} from 'ol/proj'
// import TileLayer from 'ol/layer/Tile'
// import OSM from 'ol/source/OSM'
import Point from 'ol/geom/Point'
import Select from 'ol/interaction/Select';
import { Vector as VectorSource, } from 'ol/source'
import { Tile as TileLayer, Vector as VectorLayer, } from 'ol/layer'
import XYZ from 'ol/source/XYZ'
import GeoJSON from 'ol/format/GeoJSON'
import TopoJSON from 'ol/format/TopoJSON'
import {
Circle as CircleStyle,
Fill,
Stroke,
Style,
Text
} from 'ol/style';
export default {
props:{
defaultConfig:{
type:Object,
default:()=>{
return{
name:'',
lat:null,
lng:null,
}
}
},
styleConfig:{ // 地块颜色,文字设置
type:Object,
default:()=>{}
},
selectStyleConfig:{ // 选中地块颜色,文字样式设置
type:Object,
default:()=>{}
}
},
data () {
return {
colors:['red','green','blue'],
map: null,
view: null,
options: {
zoom: 10,
center: [113.570594, 34.829485]
},
point:[],
geoJSonData: null, // 要绘制的区域
iconFeature:null, // marks
iconVectorLayer:null,//marks vectorLayer
// styleSelectedDefaultConfig:{}, // 选中样式默认设置
}
},
created(){
if(this.defaultConfig?.lag&&this.defaultConfig?.lng){
this.options.center = [this.defaultConfig?.lng,this.defaultConfig?.lag]
}
},
computed:{
styleDefaultConfig:{ // 地块样式默认设置
get(){
return{
textAlign:this.styleConfig?.textAlign||"center",
justify:this.styleConfig?.justify||"center",
areaFillColor:this.styleConfig?.areaFillColor||'rgba(47, 209, 117, 0.3)',
areaStrokeColor:this.styleConfig?.areaStrokeColor||'#2FD175',
textFillColor:this.styleConfig?.textFillColor||'#2FD175',
textStrokeColor:this.styleConfig?.textStrokeColor||'#fff'
}
},
set(){}
},
styleSelectedDefaultConfig:{
get(){
return{
textAlign:this.selectStyleConfig?.textAlign||"center",
justify:this.selectStyleConfig?.justify||"center",
areaFillColor:this.selectStyleConfig?.areaFillColor||'rgba(47, 209, 117, 0.7)',
areaStrokeColor:this.selectStyleConfig?.areaStrokeColor||'#2FD175',
textFillColor:this.selectStyleConfig?.textFillColor||'#2FD175',
textStrokeColor:this.selectStyleConfig?.textStrokeColor||'#fff',
}
},
set(){
}
}
},
mounted () {
this.point =this.options.center || [113.625351, 34.746303]
this.initMap(this.options)
},
methods: {
initMap (options = {}) {
this.view = new View({
projection: 'EPSG:4326',
center: options.center || [113.625351, 34.746303], // 郑州
zoom: options.zoom || 12
})
this.map = new Map({
target: this.$refs.map,
layers: [
new TileLayer({
title: '网格',
source: new XYZ({
visible: true,
wrapX: true,
url: '地图影像'
})
})
],
view: this.view
})
this.addGeoJson()
// this.addTopoJson()
},
/**
* 使用TopoJson
*/
addTopoJson () {
if (this.dynamicBboundary) {
this.map.removeLayer(this.dynamicBboundary)
}
const features = new TopoJSON({
featureProjection: 'EPSG:4326'
}).readFeatures(this.geoJSonData)
const source = new VectorSource({
features
// url: 'https://geo.datav.aliyun.com/areas_v3/bound/410000_full.json',
// format: new GeoJSON()
})
this.dynamicBboundary = new VectorLayer({
source: source,
className: 'boundary',
style: {
'fill-color': 'rgba(255, 255, 255, 0.01)',
'stroke-width': 5,
'stroke-color': '#1469e9',
'circle-radius': 5,
'circle-fill-color': 'rgba(255, 255, 255, 0.6)',
'circle-stroke-width': 1,
'circle-stroke-color': '#319FD3'
}
})
this.map.addLayer(this.dynamicBboundary)
const feature = source.getFeatures()[0]
const polygon = feature.getGeometry()
console.log('polygon', polygon)
this.view.fit(polygon, { padding: [170, 50, 30, 150] })
},
/**
* 设置样式
*/
createStyle(feature) {
let styleConfig={
textAlign:feature.get('name')===this.selectStyleConfig.name?this.styleSelectedDefaultConfig.textAlign:this.styleDefaultConfig.textAlign,
justify:feature.get('name')===this.selectStyleConfig.name?this.styleSelectedDefaultConfig.justify:this.styleDefaultConfig.justify,
areaFillColor:feature.get('name')===this.selectStyleConfig.name?this.styleSelectedDefaultConfig.areaFillColor:this.styleDefaultConfig.areaFillColor,
areaStrokeColor:feature.get('name')===this.selectStyleConfig.name?this.styleSelectedDefaultConfig.areaStrokeColor:this.styleDefaultConfig.areaStrokeColor,
textFillColor:feature.get('name')===this.selectStyleConfig.name?this.styleSelectedDefaultConfig.textFillColor:this.styleDefaultConfig.textFillColor,
textStrokeColor:feature.get('name')===this.selectStyleConfig.name?this.styleSelectedDefaultConfig.textStrokeColor:this.styleDefaultConfig.textStrokeColor
}
return new Style({
fill:new Fill({
color:styleConfig.areaFillColor
}),
stroke:new Stroke({
color:styleConfig.areaStrokeColor,
width:2
}),
text: new Text({
font: '16px PingFang SC',
textAlign:styleConfig.textAlign,
justify:styleConfig.justify,
text:feature.get('name'),
fill: new Fill({
color: styleConfig.textFillCOlor,
}),
stroke:new Stroke({
color:styleConfig.textStrokeColor,
width:2
}),
}),
});
},
/**
*设置选中的样式
*/
setSelectStyle(feature) {
return new Style({
fill:new Fill({
color:this.styleSelectedDefaultConfig.areaFillColor
}),
stroke:new Stroke({
color:this.styleSelectedDefaultConfig.areaStrokeColor,
width:2
}),
text: new Text({
font: '16px PingFang SC',
textAlign:this.styleSelectedDefaultConfig.textAlign,
justify:this.styleSelectedDefaultConfig.justify,
text:feature.get('name'),
fill: new Fill({
color: this.styleSelectedDefaultConfig.textFillCOlor,
}),
stroke:new Stroke({
color:this.styleSelectedDefaultConfig.textStrokeColor,
width:2
}),
}),
});
},
/**
* 添加geoGson 数据
*/
addGeoJson () {
// const features = new GeoJSON({
// featureProjection: 'EPSG:4326'
// }).readFeatures(this.henan)
// const source = new VectorSource({
// features
// // url: 'https://geo.datav.aliyun.com/areas_v3/bound/410000_full.json',
// // format: new GeoJSON()
// })
const source = new VectorSource({
url: 'https://geo.datav.aliyun.com/areas_v3/bound/410100_full.json',
format: new GeoJSON()
})
const vectorLayer = new VectorLayer({
source: source,
style:this.createStyle
})
this.map.addLayer(vectorLayer)
if(this.selectStyleConfig?.name){
this.setLocationMark()
}
this.handlePolygon()
},
handlePolygon(){
const polygonClick = new Select({
style: this.setSelectStyle,
});
this.map.addInteraction(polygonClick);
polygonClick.on('select',(e)=>{
this.point=e.selected[0].get('center')
// console.log('point',this.point)
this.setLocationMark()
this.$emit('click',e.selected,e)
})
},
setLocationMark(){
if(this.iconVectorLayer){
this.map.removeLayer(this.iconVectorLayer)
this.iconVectorLayer=null
// return false
}
this.iconFeature = new Feature({
geometry: new Point(this.point),
// name: 'Null Island',
// population: 4000,
// rainfall: 500,
});
const iconStyle1 = new Style({
image: new CircleStyle({
radius: 8,
fill: new Fill({color: '#2FD175'}),
stroke: new Stroke({color: '#fff', width: 3}),
size:[16,16]
}),
});
this.iconFeature.setStyle(iconStyle1);
const vectorSource = new VectorSource({
features: [this.iconFeature],
});
this.iconVectorLayer = new VectorLayer({
source: vectorSource,
});
this.map.addLayer(this.iconVectorLayer)
}
}
}
</script>
<style lang="scss" scoped>
.map-container {
width: 100%;
height: 800px;
}
</style>