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>
实现效果: