本篇介绍一下使用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);