vue3-openlayers WebGL裁剪图层,双图层拼接显示

104 阅读2分钟

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

29.gif

<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);

30.gif