2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
This article introduces how to use openlayers WebGL to clip layers and display two layers together
Use of layer prerender and postrender events
WebGL scissorUse of methods
The scissor method specifies a clipping region that is used to limit the drawing area to its defined box area.
gl.scissor(x, y, width, height);
parameter:
x, specifies the horizontal coordinate of the lower left corner of the box-shaped cropping area. The default value is 0.
y, specifies the vertical coordinate of the lower left corner of the box-shaped cropping area. The default is 0.
width is a non-negative number used to determine the width of the box clipping area. The default is the width of the canvas.
height, a non-negative number used to specify the height of the box-shaped cropping area. The default is the height of the canvas.
<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>
If you want to stitch the layers together in the upper left corner, just modify this sentence
gl.scissor(bottomLeft[0],topRight[1]-height , width, height);