本篇介绍一下使用openlayers WebGL裁剪图层,双图层拼接显示
1 需求
- WebGL裁剪图层,双图层拼接显示
2 分析
-
图层prerender和postrender事件的使用
-
WebGL scissor方法的使用
scissor方法指定了一个裁剪区域,用来将绘图区域限制在其限定的盒形区域内。
gl.scissor(x, y, width, height);
参数:
x,指定盒形裁剪区域左下角所在的横坐标,默认为 0。
y,指定盒形裁剪区域左下角的纵坐标,默认为 0。
width,用来确定盒型裁剪区域宽度的非负数,默认为 canvas 的宽度。
height,用以指定盒形裁剪区域高度的非负数,默认为 canvas 的高度。
3 实现
<template><div id="map" class="map"></div><div class="toolbar"><el-slider v-model="rateH" :min="1" :max="100" :step="1" @input="handleInput"></el-slider><el-slider v-model="rateV" :min="1" :max="100" :step="1" @input="handleInput"></el-slider></div>
</template><script setup lang="ts">
import { Map, View } from 'ol';
import { WebGLTile as WebGLTileLayer } from 'ol/layer';
import { fromLonLat, get } from 'ol/proj';
import { XYZ } from 'ol/source';
import { getRenderPixel } from 'ol/render.js';const projection = get('EPSG:3857');
const key = '替换为天地图key';
const layerTypeMap = {vector: ['vec', 'cva'], // [矢量底图, 矢量注记]image: ['img', 'cia'], // [影像底图, 影像注记]terrain: ['ter', 'cta'] // [地形晕渲, 地形注记]
};
let map = null;
const rateH = ref(50);
const rateV = ref(50);const imageLayer = new WebGLTileLayer({source: new XYZ({url: `https://t{0-7}.tianditu.gov.cn/DataServer?T=${layerTypeMap['image'][0]}_w&tk=${key}&x={x}&y={y}&l={z}`,projection})
});const terrainLayer = new WebGLTileLayer({source: new XYZ({url: `https://t{0-7}.tianditu.gov.cn/DataServer?T=${layerTypeMap['terrain'][0]}_w&tk=${key}&x={x}&y={y}&l={z}`,projection})
});onMounted(() => {initMap('image');
});const initMap = (layerType = 'image') => {// c: 经纬度 w: 墨卡托const matrixSet = 'w';map = new Map({target: 'map',layers: [// 底图terrainLayer,imageLayer,// 注记new WebGLTileLayer({source: new XYZ({url: `https://t{0-7}.tianditu.gov.cn/DataServer?T=${layerTypeMap[layerType][1]}_${matrixSet}&tk=${key}&x={x}&y={y}&l={z}`,projection})})],view: new View({center: fromLonLat([116.406393, 39.909006]),projection: projection,zoom: 5,maxZoom: 17,minZoom: 1})});imageLayer.on('prerender', function (event) {const gl = event.context;gl.enable(gl.SCISSOR_TEST);//获取地图[宽,高]像素(数组)const mapSize = map.getSize();// getRenderPixel从地图视口的CSS像素获取事件的画布上下文的像素。// 获取canvas坐标的左下和右上点坐标const bottomLeft = getRenderPixel(event, [0, mapSize[1]]);const topRight = getRenderPixel(event, [mapSize[0], 0]);const width = Math.round((topRight[0] - bottomLeft[0]) * (rateH.value / 100));const height = Math.round((topRight[1] - bottomLeft[1] )* (rateV.value / 100));;gl.scissor(bottomLeft[0], bottomLeft[1], width, height);});imageLayer.on('postrender', function (event) {const gl = event.context;gl.disable(gl.SCISSOR_TEST);});
};const handleInput = val => {map.render();
};
</script>
<style scoped lang="scss">
.map {width: 100%;height: 100%;
}.toolbar {position: absolute;top: 20px;left: 100px;width: 500px;display: flex;justify-content: center;align-items: center;color: #fff;.el-slider {margin-right: 50px;}div {width: 100px;height: 30px;display: flex;justify-content: center;align-items: center;}
}
</style>
如果想拼接图层放在左上角,只需要修改这句
gl.scissor(bottomLeft[0],topRight[1]-height , width, height);