You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为OpenLayers的range控件添加纵向分割线实现图层滑动

实现带纵向分割线的OpenLayers图层滑动控件

我目前使用OpenLayers实现了图层滑动控件,现在想要改成带有贯穿地图的纵向分割线的同款功能。现有实现代码如下,需要调整以添加分割线效果:

现有代码

HTML部分

<input id="swipe" type="range" style="width: 100%;">

TypeScript部分

const imagery = new TileLayer({
  source: new XYZ({
    url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + '19eciGimIzBlp29oJUJO',
    maxZoom: 20,
  }),
});
map.addLayer(imagery);

const swipe = <HTMLInputElement> document.getElementById('swipe');

imagery.on('prerender', function (event) {
  const gl = <WebGLRenderingContext> event.context;
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.enable(gl.SCISSOR_TEST);

  const mapSize = map.getSize(); // [width, height] in CSS pixels

  // get render coordinates and dimensions given CSS coordinates
  const bottomLeft = getRenderPixel(event, [0, mapSize[1]]);
  const topRight = getRenderPixel(event, [mapSize[0], 0]);

  const width = (topRight[0] - bottomLeft[0]) * (Number(swipe.value) / 100);
  const height = topRight[1] - bottomLeft[1];
  gl.scissor(bottomLeft[0], bottomLeft[1], width, height);

});

imagery.on('postrender', function (event) {
  const gl = <WebGLRenderingContext> event.context;
  gl.disable(gl.SCISSOR_TEST);
});
const listener = function () {
  map.render();
};
swipe.addEventListener('input', listener);
swipe.addEventListener('change', listener);

修改方案:添加纵向分割线

要实现贯穿地图的纵向分割线,需要在postrender事件中绘制一条垂直直线,位置与滑动条的数值对应。修改后的代码如下:

修改后的TypeScript代码

const imagery = new TileLayer({
  source: new XYZ({
    url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + '19eciGimIzBlp29oJUJO',
    maxZoom: 20,
  }),
});
map.addLayer(imagery);

const swipe = <HTMLInputElement> document.getElementById('swipe');

imagery.on('prerender', function (event) {
  const gl = <WebGLRenderingContext> event.context;
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.enable(gl.SCISSOR_TEST);

  const mapSize = map.getSize();
  const bottomLeft = getRenderPixel(event, [0, mapSize[1]]);
  const topRight = getRenderPixel(event, [mapSize[0], 0]);

  const width = (topRight[0] - bottomLeft[0]) * (Number(swipe.value) / 100);
  const height = topRight[1] - bottomLeft[1];
  gl.scissor(bottomLeft[0], bottomLeft[1], width, height);
});

imagery.on('postrender', function (event) {
  const gl = <WebGLRenderingContext> event.context;
  gl.disable(gl.SCISSOR_TEST);

  // 绘制纵向分割线
  const mapSize = map.getSize();
  const swipePositionX = (mapSize[0] * Number(swipe.value)) / 100;
  const bottomLeft = getRenderPixel(event, [swipePositionX, mapSize[1]]);
  const topRight = getRenderPixel(event, [swipePositionX, 0]);

  // 设置线条样式
  gl.lineWidth(2);
  gl.strokeStyle = '#000';
  gl.beginPath();
  gl.moveTo(bottomLeft[0], bottomLeft[1]);
  gl.lineTo(topRight[0], topRight[1]);
  gl.stroke();
});

const listener = function () {
  map.render();
};
swipe.addEventListener('input', listener);
swipe.addEventListener('change', listener);

关键修改说明

  • 在postrender事件中,计算滑动条对应的横向位置,转换为渲染坐标
  • 使用WebGL的绘图API绘制垂直直线,可自定义线条宽度和颜色
  • 确保在关闭裁剪测试后绘制线条,避免线条被原有裁剪逻辑影响

内容的提问来源于stack exchange,提问作者Funn_Bobby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 10:29:58