通过控制图层,层级和大小来实现图层透视功能。 主要使用图层监听事件 prerender监听图层渲染之前,postrender监听图层渲染之后。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style type="text/css">
    .map {
      height: 500px;
      width: 100%;
    }
  </style>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.6.1/css/ol.css" />
  <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.6.1/build/ol.js"></script>
  <body>
    <div id="map" class="map"></div>
  </body>
  <script>
    // 图层
    var roads = new ol.layer.Tile({
      source: new ol.source.XYZ({
        url: 'https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
      })
    })

    // 图层2
    var imagery = new ol.layer.Tile({
      source: new ol.source.XYZ({
        url: 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'
      })
    })

    // 实例
    const container = document.getElementById('map')

    var map = new ol.Map({
      target: container,
      layers: [roads, imagery],
      view: new ol.View({
        center: ol.proj.fromLonLat([37.41, 8.82]),
        zoom: 4
      })
    })

  </script>
</html>

  • 这里我们创建了两个图层,记住图层的默认层级都是后面添加的大于前面的层级。
  • 要实现图层透视的效果,其实就是在基础图层上固定范围绘制上图层来达到效果。

获取鼠标在地图上的坐标位置

   // 地图像素位置
    let mousePosition = null

    container.addEventListener('mousemove', function (event) {
      // getEventPixel(event) 根据事件当前位置 返回地图像素位置。
      mousePosition = map.getEventPixel(event)

      // 重新渲染地图 render()
      map.render()
    })

    container.addEventListener('mouseout', function () {
      mousePosition = null
      map.render()
    })
  1. 创建全局变量(mousePosition)实时保存鼠标地理位置。
  2. 通过监听容器的鼠标移入事件获取当前位置窗口位置,使用getEventPixel()转换为地理位置。
  3. 监听容器的鼠标移出事件取消地理位置。
  4. 每次监听都需要重绘地图,用于透视图层内容的更新。

监听图层事件

 
    // 半径
    let radius = 75
    // 图层渲染之前
    imagery.on('prerender', function (event) {
      const ctx = event.context
      ctx.save() // 保存
      ctx.beginPath()
      if (mousePosition) {
        ctx.arc(mousePosition[0], mousePosition[1], radius, 0, 2 * Math.PI)
        ctx.lineWidth = (5 * radius) / radius
        ctx.strokeStyle = 'rgba(0,0,0,0.5)'
        ctx.stroke()
      }
      // 使用裁剪 只加载 圆内数据
      ctx.clip()
    })

    // 图层渲染之后
    imagery.on('postrender', function (event) {
      const ctx = event.context
      ctx.restore()
    })
  1. 这里绘制的是圆形,你可以自定义其他图形。
  2. 通过图层事件prerender图层渲染之前,在监听中返回的图层实例canvas。这里一定要先保存状态ctx.save(),通过mousePosition获取鼠标的坐标,随意绘制图形,使用clip()裁剪画布,只展示裁剪后的内容。
  3. 通过postrender图层渲染之后。恢复保存的canvas内容展示。

使用Vector图层通过绘制多边行的方法

  • 绘制出省市区的多边行,把该图层添加到地图图层上,就实现了绘制省市区图形。

Vector

  • 矢量图层: 在客户端呈现的矢量数据。构成一个矢量图层需要一个数据源(source)和一个样式(style),数据源构成矢量图层的要素,样式规定要素显示的方式和外观。一个矢量图层包含一个到多个要素(feature),每个要素由地理属(geometry)和其他属性组成。
  • 常用于从数据库中请求数据,接受数据,并将接收的数据解析成图层上的信息。如将鼠标移动到中国,相应的区域会以红色高亮显示出来,高亮便是矢量图层的行为。
  
    var map = new ol.Map({
      target: 'map'
    })

    // 图层
    var layerTile = new ol.layer.Tile({
      source: new ol.source.XYZ({
        url: 'https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
      })
    })
    // 视图
    var view = new ol.View({
      center: ol.proj.fromLonLat([130.41, 28.82]),
      zoom: 4
    })

    map.setView(view)
    map.addLayer(layerTile)
  

绘制图层

js复制代码    // 设置图层
    var areaLayer = new ol.layer.Vector({
      source: new ol.source.Vector({
        features: []
      })
    })
    // 添加图层
    map.addLayer(areaLayer)

    let areaFeature = []
    geo.forEach((g) => {
      var areaFeatureTem = null
      let lineData = g.features[0]
      if (lineData.geometry.type == 'MultiPolygon') {
        areaFeatureTem = new ol.Feature({
          geometry: new ol.geom.MultiPolygon(lineData.geometry.coordinates).transform('EPSG:4326', 'EPSG:3857')
        })
      } else if (lineData.geometry.type == 'Polygon') {
        areaFeatureTem = new ol.Feature({
          geometry: new ol.geom.Polygon(lineData.geometry.coordinates).transform('EPSG:4326', 'EPSG:3857')
        })
      }
      areaFeatureTem.setStyle(
        new ol.style.Style({
          fill: new ol.style.Fill({ color: '#4e98f444' }),
          stroke: new ol.style.Stroke({
            width: 3,
            color: [71, 137, 227, 1]
          })
        })
      )
      areaFeature.push(areaFeatureTem)
    })

    // 加入组装好的数据
    areaLayer.getSource().addFeatures([...areaFeature])
  • 先创建图层,然后创建要素。多边行在要素中主要分为两种,MultiPolygonPolygon,都是表示多边行的。不同的是MultiPolygon数据格式是4维数组,Polygon是3维数组。最后把创建好的要素放入图层中。

1、TileLayer 瓦片图层。一般加载切片图层(wmts,wms)

天地图(wmts)

const tempLayer = new TileLayer({
  visible: true,
  projection: "EPSG:4326",
  source: new XYZ({
    visible: true,
    url: "https://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=" + token,
  }),
  opacity: 1,
});
 
      // 加载 wms 服务
      let wmsLayer = new TileLayer({
        preload: Infinity,
        source: new TileWMS({
          url: "http://localhost:8090/geoserver/keshan/wms",
          //定义服务的请求参数
          params: {
            LAYERS: "",  //图层名称
            FORMAT: "image/png",
            VERSION: "1.1.1",
            tiled: true,
            STYLES: "",
            exceptions: "application/vnd.ogc.se_inimage",
            cql_filter: "",  //过滤条件
          },
          //可选,定义请求瓦片的大小 级别等,不需要的话可注释
          tileGrid: new ol.tilegrid.TileGrid({
            resolutions: this.getTileResolutions(),
            origin: [-180, 90],
            tileSize: 512,
          }),
          serverType: "geoserver",
          crossOrigin: "anonymous",  //跨域请求,主要涉及到地图图片的导出
        }),
        maxZoom: 21,
        minZoom: 0,
        zIndex:  100,
        properties: {}, //自定义一些图层的属性
      });

wmts服务

      // 加载 wmts 服务
      const matrixIds = new Array(20);
      for (let z = 0; z < 21; ++z) {
        matrixIds[z] = "EPSG:4490_dzdtz:" + z;
      }
      //自己瓦片的比例尺
      var resolutions = [
        1.4078260157100582, 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,
      ];
      let wmtsLayer = new TileLayer({
        preload: Infinity,
        source: new WMTS({
          url: url,
          layer: "",
          matrixSet: "EPSG:4490_dzdtz", //瓦片矩阵集的名称
          format: "image/jpeg",
          tileGrid: new WMTSTileGrid({
            tileSize: [256, 256],
            extent: [-180.0, -270.4034600217749, 180.4034600217749, 90.0],
            origin: [-180.0, 90.0],
            resolutions: resolutions,
            matrixIds: matrixIds,  //矩阵级别
          }),
          style: "",
          wrapX: true,
        }),
        maxZoom: 21,
        minZoom: 0,
        visible: false,
        zIndex: 100,
        properties: {},
      });
  • wmts有些参数比较复杂,需要自己去看服务元数据的参数,比如矩阵也就是切片层级的名称,瓦片层级等。

2、VectorLayer 矢量图层,这个图层主要是添加自己的绘制的一些要素

 const maskLayer = new VectorLayer({
    preload: Infinity,
    source: new VectorSource({
      features: [],  //图层要素
      //geojson的读取方式
      //features: [new GeoJSON().readFeature(masked)]
      //url的读取方式
      //url: "/static/wgs84jz.json",
    }),
    //图层样式
    style: new Style({
      stroke: new Stroke({
        color: "#01FDFF", 
        width: 3,
        opacity: 1,
      }),
      fill: new Fill({
        color: "#061F57",
      }),
    }),
    visible: true,
    zIndex: 200,
    opacity: 0.3,  //图层透明度
    projection: "EPSG:4326",
  });

VectorLayer使用比较灵活,可以自定义样式,图层要素等

3、ImageLayer 影像图层

  • 它是基于图片的图层类型,适用于一次性加载一张完整的图片来显示地图数据。基本类似于TileLayer,但是ImageLayer不能加载切片
  let wmsLayer = new ImageLayer({
    source: new ImageWMS({
      crossOrigin: "anonymous",
      url: url,
      params: {
        LAYERS: param.layers,
        FORMAT: "image/png",
        VERSION: "1.1.1",
        tiled: true,
        STYLES: "",
        exceptions: "application/vnd.ogc.se_inimage",
        cql_filter: "",
      },
      serverType: "geoserver",
    }),
 
    maxZoom: 21,
    minZoom: 0,
    visible: false,
    zIndex:  100,
    properties: {},
  });

在 OpenLayers 中,VectorLayer、ImageLayer 和 TileLayer 是三种常见的图层类型,它们在加载和显示地图数据的方式上有一些区别。

VectorLayer(矢量图层)

VectorLayer 是基于矢量数据的图层类型,适用于加载和显示矢量要素数据,如点、线、多边形等。 VectorLayer 的数据通常是通过 GeoJSON、KML、GPX 等格式提供的,或者通过手动创建要素(Feature)添加到图层中。 VectorLayer 可以对矢量要素进行样式渲染、交互操作、查询等操作,具有高度的灵活性和可定制性。

ImageLayer(影像图层)

ImageLayer 是基于图片的图层类型,适用于一次性加载一张完整的图片来显示地图数据。 对于小范围区域或静态图片,可以使用 ImageLayer。通过设置图层的 source 属性为 ol.source.ImageStatic,可以指定图片的 URL、投影、范围等信息。 ImageLayer 适用于不需要动态切片的影像数据,例如航拍照片。

TileLayer(瓦片图层)

TileLayer 是基于切片的图层类型,适用于将地图数据分为多个小块(瓦片)进行加载和显示。 地图服务通常以瓦片的形式提供数据,因此 TileLayer 是常用的图层类型。 TileLayer 使用的图层源(source)通常是 ol.source.TileWMS、ol.source.TileArcGISRest、ol.source.OSM 等类型。这些源会自动处理切片请求,加载合适的瓦片并随着地图视图的变化进行更新。

总结

VectorLayer 适用于加载和显示矢量要素数据,具有灵活的样式渲染和交互操作能力。 ImageLayer 适用于静态或小范围的影像数据,一次性加载整张图片进行显示。 TileLayer 适用于将地图数据分为瓦片进行加载和显示,支持动态切片请求和视图变化时的更新。

//这里定义的是图层类型
const layer=new VectorLayer({
 source:vectorSource,//矢量图层源 (必须)
 style:[],//图层样式(必须)
 feature:[],//图层元素(必须)
})

1、添加/删除指定图层:map.addLayer/removeLayer(layer) 2、图层是轻量级容器从 数据源source获取数据 3、source子类分别对应不同图层类:

ol.source.ImageSource() ol.source.TileSource() ol.source.VectorSource()

Source主要有以下属性

new Ol.si=ource.VectorSource({
 attributions:,//
    attributionsCollapsible:,//布尔值  默认为true 
    projection:,//投影系
    state:'ready',//默认为'ready'
    wrapX:false,//默认为false
})
  • ol.layer.Tile()和ol.layer.Image()图层都具有相同的属性如下
new ol.layer.Tile/Image({
 opacity:.2,//透明度 区间范围为(0,1)默认为1
 visible:true,
 extent:[],//图层范围的边界范围
 zIndex:2,//图层渲染的层级
 minResolution:1,//最小分辨率
 maxResolution:6, //最大分辨率
 reload:0, //预加载
 source:new ol.source.TileSource()/ImageSource()//图层源,
 map:  ,//把图层覆盖在地图上,地图不会在它的图层集合中管理这个图层,这个图层将被呈现在顶部,这对于临时层非常有用。
})

ol.layer.Tile() 平铺图层 ol.layer.image() 图像图层

矢量图层

new ol.layer.Vector({//以下为图层的属性选项, 都可设置,所以皆有getter/setter
 opacity:2,//透明度 区间范围为(0, 1) 默认为1
    visible:true,//显示属性 布尔值 默认为true
    extent:[],//图层渲染的边界范围。该层将不会在此范围之外呈现
    zIndex:2,//图层渲染的索引层级。在渲染时,图层将被排序,首先是z-idnex,然后是位置,当为undefined时,对于添加到映射的layers集合中的层,zIndex为0,或者当使用该层的setMap()方法时,zIndex为无穷大
    minResolution:3,//该层可见的最小分辨率(包括在内)
    maxResolution:6,//该层可见的最大分辨率(包括在内)
    renderOrder:,//呈现顺序。函数用于在呈现前对特性进行排序。默认情况下,特性是按照创建它们的顺序绘制的。使用null来避免排序,但是得到一个未定义的绘制顺序
    renderBuffer:100,//默认为100 缓冲区
    renderMode:'vector',//默认为'vector' 矢量图层的渲染模式
    source:new ol.source.VectorSource(),//图层源
    map:  ,//把图层覆盖在地图上,地图不会在它的图层集合中管理这个图层,这个图层将被呈现在顶部,这对于临时层非常有用
    declutter:false,//默认为false 整理图片和文字。清理应用于所有图像和文本样式,优先级由样式的z-index定义。z-index指数越低,优先级越高
    style:new ol.style.Style(),//图层样式
    updateWhileAnimating:false,//默认为false 
    updateWhileInteracting:false,//默认为false
})

其中渲染模式有两种: image : 矢量图层被渲染为图像,性能很好,但是点符号和文本总是随着视图的旋转 动画中会被缩放。 vector:矢量图层为呈现为向量,即使在动画中也能精准的渲染,性能较慢。

Feature

Feature 用于地理特征的矢量元素,具有几何geometry和其他属性,类似于矢量文件格式(如GeoJSON)中的特性。 1、添加矢量元素:addFeature(feature) 2、移除矢量图层 clear()

const feature=new ol.Feature({
 geometry: new ol.geom.Polygon(polyCoords),
 labelPoint:new ol.geom.Point(labelCoords),
 style:new ol.style.Style({}),
 name: ‘My Polygon’
})

3、一个feature只有一个默认几何属性geometry,可以有任意数量的命名集合图形:

获取默认几何属性: feature.getGeometry()

设置几何属性:feature.setGeometry(geometry)

设置几何属性名:feature.setGeometryName(name)

矢量元素要呈现的几何图形的特征属性、几何图形或函数由geometry属性选项设定,主要有以下几种子类模型: 1、ol.geom.Circle():圆形 2、ol.geom.Geometry() 几何图形 3、ol.geom.LinearRing 环线 4、ol.geom.LineString 线段

feature的稳定标志符ID: 设置feature的ID: feature.setId(id); 当id可能相同时,可以加以区分:feature.setId(id+''featureName"); 获取的featureID: vector.getSource().getFeatureById()/vectorsource.getFeatureById()

feature的set(key,value,option) 设置key: feature.set(“keyName”,name) keyName是字符串 获取key: feature.get(“keyName”)

Style

矢量特征呈现样式的容器。在重新呈现使用样式的特性或图层之前,通过set*()方法对样式及其子元素所做的任何更改都不会生效。

new ol.style.Style({
 geometry:new geom.LineString(),
 fill:new style.Fill({
  //填充样式
  color:color
 }),
 image:new style.Image({
   opacity:,//数值
        rotateWithView:,//布尔值
        rotation:,//数值
        scale:
 }),
 image:new style.Icon({//可以使用图片资源
  anchor:[0.50.5]//锚。默认值是图标中心 默认值是[0.5,0.5]
        anchorOrigin:'top-left',//锚的原点:左下角、右下角、左上方或右上方。默认是左上
        anchorXUnits:'fraction',//指定锚点x值的单位。'fraction'的值表示x值是图标的'fraction'。'pixels'的值表示像素中的x值,默认为'fraction'
        anchorYUnits:'fraction',//指定锚点y值的单位。'fraction'的值表示y值是图标的'fraction'。'pixels'的值表示像素中的y值,默认为'fraction'
        color:color,//颜色、渐变或图案
        crossOrigin:,
        img:,//图标的图像对象  如果没有提供src选项,则必须已经加载了提供的图像
        imgSize:,//
        offset:[0,0].//偏移值,默认为[0,0]
        offsetOrigin:'top-left',//偏移量的原点,bottom-left, bottom-right, top-left or top-right. 默认是`top-left`
        opacity:1,//默认是1  (0,1)
        scale:1,//默认是1
        rotation:0//以弧度旋转(顺时针方向正旋转) 默认为0
        size:,//图标大小(以像素为单位)。可与偏移量一起用于定义要从原点(sprite)图标图像使用的子矩形
        src:'',//图像URL源
        rotateWithView:false,//是否旋转视图中的图标  默认为false 
 }),
 stroke:new ol.style.Stroke({
  //描绘
  width:,//宽
  color:color//颜色、渐变或图案
  lineCap:'round',//线帽风格  butt, round, 或者 square 默认 round
        lineJoin:'round',//线连接方式 bevel, round, 或者 miter 默认 round
        lineDash: []//线间隔模式 这个变化与分辨率有关 默认为undefined Internet Explorer 10和更低版本不支持
        lineDashOffset:0,//线段间隔偏移 默认0
        miterLimit:10,// 默认10
 }),
 text:new ol.style.Text({
  //文字
   font:'',//默认是'10px sans-serif'
        text:'',//文本内容
        textAlign:'center',//文本对齐 'left', 'right', 'center', 'end' 'start'.针对于placement: 'point',默认为'center';针对于placement: 'line',默认是让渲染器选择不超过maxAngle的位置
        textBaseline:'middle',//文本基线  'bottom', 'top', 'middle', 'alphabetic', 'hanging', 'ideographic' 默认'middle'
        placement:'',//文本布置
        scale:,
        padding:[0,0,0,0],//文本周围的像素填充。数组中值的顺序是[top, right, bottom, left]
        fill:new ol.style.Fill(),//如果未设置,默认未#333
        stroke:new ol.style.Stroke(),
        offsetX:0,//水平文本偏移量(以像素为单位)。正值将把文本右移。默认0
        offsetY:0,//垂直文本偏移量(以像素为单位)。正值会将文本向下移动。默认0
        rotation:0//默认0
        rotateWithView:false,
        backgroundFill:  ,//当placement:“point”时,填充文本背景的样式。默认为无填充 
        backgroundStroke: ,//当placement:“point”时,描绘文本背景的样式。默认为无描绘
 })
})

ol.geom.Geomtry() 方法 : 1 1、getProperties()获取一个包含所有属性名和值的对象 2、getClosestPoint(point,option) 将几何图形的最近点作为坐标返回到经过的点。 3、getExtent() 获取几何的范围 4、getKeys()获取几何的属性名称列表 5、intersectsCoordinate(coordunate) 判断该集合是否包含指定的坐标 返回true 或者false

ol.geom.Circle() 方法 : 1、getCenter()返回中心坐标 2、applyTransform(transformFn) 对几何图形的每个坐标应用一个变换函数,在适当的位置修改几何图形。不想修改的时候需要克隆一个,再用此函数。 3、getFirstCoordinate()返回几何图形的第一个坐标 4、getLastCoordinate()返回几何图形的最后一个坐标 5、setCenter(center) 将圆心设置为 coordinate 6、setCenterAndRadius(center,radius,option) 设置圆的中心(coordinate)和半径(number)

ol.geom.LineString(coordinates, opt_layout)
new ol.geom.lineString({
 coordinates:[],//坐标,
 layout:layout
})

方法:

  1. appendCoordinate(coordinate) 将经过的坐标追加到linestring的坐标里
  2. applyTransform(transformFn) 对几何图形的每个坐标应用一个变换函数。在适当的位置修改几何图形。如果不想修改几何图形,请首先clone()它,然后在克隆上使用此函数
  3. forEachSegment(callback)遍历每条线段,调用提供的回调函数,如果回调函数返回一个真值,则函数立即返回该值。否则函数返回false
  4. getCoordinates/setCoordinates()返回线段的坐标/设置线段的坐标
  5. getLastCoordinate()返回几何图形的第一个坐标

ol.geom.Point(coordinates, opt_layout) new ol.geom.Point

方法

  1. applyTransform(transformFn) 对几何图形的每个坐标应用一个变换函数。在适当的位置修改几何图形。如果不想修改几何图形,请首先clone()它,然后在克隆上使用此函数
  2. getCoordinates()返回点的坐标
  3. setCoordinates(coordinates, opt_layout)设置点的坐标
  4. getFirstCoordinate()返回几何图形的第一个坐标
  5. getLastCoordinate()返回几何图形的最后一个坐标
  6. getLayout()返回几何图形的Layout
  7. getType()得到这个几何图形的类型