React中使用openLayer画地图

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值