Openlayers 卷帘地图

Openlayers 瓦片灰度处理

Openlayers 卷帘地图

前言

一般底图中都有“图层切换”这个最基本的功能,可以查看想要查看的图层。

当想对两个图层比较直观的对比的时候,卷帘图层是一个很好的实现方式。

拖动分界线可以很方便的查看任意地方两个图层的变化。

实现

在 openlayers 中的实现方式是:对需要卷帘的图层添加渲染前事件(prerender)和渲染后事件(postrender)。

prerender:这里用 canvas 裁剪出当前图层要显示的范围

postrender:恢复下面图层的显示,否则下面图层全黑显示

具体代码实现如下:

HTML代码:

    <div ref="sliderEl" :style="{left:left+'px'}" class="slider" @mousedown="onMouseDown">
      <div class="circle" @mousedown="onMouseDown" />
      <div class="slider-left">矢量图</div>
      <div class="slider-right">卫星图</div>
    </div>

JS部分:

<script>
import { Map, View } from 'ol'
import TileLayer from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'

import mapUrls from '@/GIS/mapUrls.js'

export default {
  data() {
    return {
      businessMap: null,
      baseLayers: [],
      topLayer: null,
      mapWidth: 100,
      minClientLeft: 0,
      maxClientLeft: 0,
      left: 50,
      clientleft: 0,
      isMove: false
    }
  },
  created() {
    this.createdBaseLayer()
  },
  mounted() {
    // 初始化时,卷帘处在地图中间位置,根据地图宽高计算
    this.mapWidth = this.$refs.mapEl.offsetWidth
    this.left = this.mapWidth / 2
    // 保证卷帘始终在地图内,并两边留一部分
    this.minClientLeft = this.$refs.mapEl.offsetLeft + 50
    this.maxClientLeft = this.minClientLeft + this.mapWidth - 100

    this.businessMap = new Map({
      target: 'business-map',
      layers: this.baseLayers,
      view: new View({
        projection: 'EPSG:4326',
        center: [119.923451, 30.385335],
        zoom: 11.5,
        maxZoom: 19,
        minZoom: 5
      })
    })

    // 拖动事件注册在 doucment 上面,防止拖拽过程中鼠标丢失情况
    document.addEventListener('mousemove', this.onMouseMove)
    document.addEventListener('mouseup', this.onMouseUp)
  },
  beforeDestroy() {
    document.removeEventListener('mousemove', this.onMouseMove)
    document.removeEventListener('mouseup', this.onMouseUp)
  },
  methods: {
    createdBaseLayer() {
      const vecLayer = new TileLayer({
        source: new XYZ({
          url: mapUrls['aMap-vec-a']
        }),
        title: '矢量底图'
      })
      this.baseLayers.push(vecLayer)

      this.topLayer = new TileLayer({
        source: new XYZ({
          url: mapUrls['aMap-img-n']
        }),
        title: '影像底图'
      })
      this.baseLayers.push(this.topLayer)

      this.topLayer.on('prerender', (e) => {
        const ctx = e.context
        const width = ctx.canvas.width * (this.left / this.mapWidth)
        ctx.save()
        ctx.beginPath()
        ctx.rect(width, 0, ctx.canvas.width - width, ctx.canvas.height)
        ctx.clip()// 裁剪
      })
      // 请求完成,渲染
      this.topLayer.on('postrender', function(e) {
        const ctx = e.context
        ctx.restore()
      })
    },

    onMouseDown(e) {
      this.isMove = true
      this.clientleft = e.clientX
      this.$refs.sliderEl.style.cursor = 'move'
    },

    onMouseMove(e) {
      if (!this.isMove) return
      if (e.clientX < this.minClientLeft || e.clientX > this.maxClientLeft) return

      const mx = e.clientX - this.clientleft
      this.clientleft = e.clientX

      this.left = this.left + mx
      this.businessMap.render()
    },

    onMouseUp() {
      this.isMove = false
      this.$refs.sliderEl.style.cursor = 'default'
    }
  }
}
</script>

 实现效果:

 

posted @ 2022-06-30 16:37  漠里  阅读(1163)  评论(6编辑  收藏  举报