本篇介绍一下使用vue3-openlayers WebGL裁剪图层,双图层拼接显示
1 需求
- vue3-openlayers WebGL裁剪图层,双图层拼接显示
2 分析
-
图层prerender和postrender事件的使用
-
WebGL scissor方法的使用
scissor方法指定了一个裁剪区域,用来将绘图区域限制在其限定的盒形区域内。
gl.scissor(x, y, width, height);
参数:
x,指定盒形裁剪区域左下角所在的横坐标,默认为 0。
y,指定盒形裁剪区域左下角的纵坐标,默认为 0。
width,用来确定盒型裁剪区域宽度的非负数,默认为 canvas 的宽度。
height,用以指定盒形裁剪区域高度的非负数,默认为 canvas 的高度。
3 实现
<template>
<ol-map
:loadTilesWhileAnimating="true"
:loadTilesWhileInteracting="true"
style="width: 100%; height: 100%"
ref="mapRef"
>
<ol-view ref="view" :center="center" :zoom="zoom" :projection="projection" />
<ol-webgl-tile-layer>
<ol-source-tianditu
layerType="ter"
:projection="projection"
:tk="key"
:hidpi="true"
></ol-source-tianditu>
</ol-webgl-tile-layer>
<ol-webgl-tile-layer @prerender="handlePreRender" @postrender="handlePostRender">
<ol-source-tianditu
layerType="img"
:projection="projection"
:tk="key"
:hidpi="true"
ref="sourceRef"
></ol-source-tianditu>
</ol-webgl-tile-layer>
<ol-webgl-tile-layer>
<ol-source-tianditu
:isLabel="true"
layerType="img"
:projection="projection"
:tk="key"
:hidpi="true"
></ol-source-tianditu>
</ol-webgl-tile-layer>
</ol-map>
<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 { fromLonLat } from 'ol/proj';
import { getRenderPixel } from 'ol/render.js';
const center = ref(fromLonLat([121, 31]));
const projection = ref('EPSG:3857');
const zoom = ref(5);
const mapRef = ref();
const key = '替换为天地图key';
const sourceRef = ref(null);
const rateH = ref(50);
const rateV = ref(50);
const handlePreRender = event => {
const gl = event.context;
gl.enable(gl.SCISSOR_TEST);
//获取地图[宽,高]像素(数组)
const mapSize = mapRef.value.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);
};
const handlePostRender = event => {
const gl = event.context;
gl.disable(gl.SCISSOR_TEST);
};
const handleInput = val => {
mapRef.value.map.render();
};
</script>
<style scoped lang="scss">
.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);