openlayers +GeoJSON 给不同的行政区显示不同的

2022-11-21  本文已影响0人  冰落寞成

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>

上一篇下一篇

猜你喜欢

热点阅读