GIS前端开发之路——Openlayers为地图增加阴影(三)

0 阅读2分钟

在VectorLayer的属性中有个renderer,通过这个属性我们可以绘制出地图轮廓阴影,具体操作如下。

首先封装出一个用于绘制的函数

// 封装的阴影绘制函数
  const drawShadow = (ctx, options) => {
    // 设置 canvas 阴影属性
    ctx.fillStyle = options.fillStyle || 'transparent'
    ctx.shadowOffsetY = options.shadowOffsetY || 0
    ctx.shadowOffsetX = options.shadowOffsetX || 0
    ctx.shadowBlur = options.shadowBlur || 0
    ctx.shadowColor = options.shadowColor || 'transparent'

    // 开始绘制路径
    ctx.beginPath()
    const arr = options.coordsArr || []
    for (let i = 0; i < arr.length; i++) {
      const data = arr[i]
      if (i === 0) {
        ctx.moveTo(data[0], data[1])
      } else {
        ctx.lineTo(data[0], data[1])
      }
    }
    ctx.closePath()
    ctx.fill()
    // 有时也需要描边,可以按需添加 ctx.stroke();
  }

根据地图轮廓重新创建出一个新的VectorSource数据

    const proVectorSource = new VectorSource({
      features: [],
      format: new GeoJSON(),
      url: localProGeoJsonUrl, // 本地GeoJSON地址
    })

然后,创建一个阴影图层

 // 阴影图层
    const shadowVectorLayer = new VectorLayer({
      source: proVectorSource,
      style: new Style({
        renderer(coordinates, state) {
          const ctx = state.context
          // 取出当前绘制要素的屏幕像素坐标
          const arr = coordinates[0][0]
          console.log(arr)
          // 开始多次绘制,创造“假3D”阴影效果
          drawShadow(ctx, {
            fillStyle: 'rgba(30, 60, 95, 1)',
            shadowOffsetY: 30,
            shadowOffsetX: 2,
            shadowColor: 'rgba(30, 60, 95, 1)',
            coordsArr: arr,
          })
          drawShadow(ctx, {
            fillStyle: 'transparent',
            shadowOffsetY: 20,
            shadowOffsetX: 2,
            shadowColor: 'rgba(56, 113, 139, 1)',
            coordsArr: arr,
          })
          // ...可以继续添加更多偏移层来增强立体感
          drawShadow(ctx, {
            fillStyle: 'transparent',
            shadowOffsetY: 15,
            shadowOffsetX: 2,
            shadowColor: 'rgba(255,255,255,1)',
            shadowBlur: 10,
            coordsArr: arr,
          })
          // ... 后续可以继续添加更多偏移层来增强立体感

          // 最后,绘制物体本身
          drawShadow(ctx, {
            fillStyle: 'rgba(70, 130, 180, 0.8)', // 物体颜色
            shadowOffsetY: 0,
            shadowOffsetX: 0,
            shadowBlur: 0,
            shadowColor: 'transparent', // 本体不需要阴影
            coordsArr: arr,
          })
        },
      }),
    })

最后再将阴影图层放在地图图层的下面

// 创建地图(不添加任何 TileLayer)
    map = new Map({
      canvasContextOptions: {
        willReadFrequently: true,
      },
      target: mapContainer.value,
      layers: [shadowVectorLayer, vectorLayer],
      controls: [],
      view: new View({
        // 初始中心点随便给,后面会自动fit
        center: [0, 0],
        zoom: 7.5,
        minZoom: 7.5,
        maxZoom: 7.5,
        projection: 'EPSG:3857', // 默认投影,GeoJSON会自动重投影
      }),
      interactions: defaultInteractions({
        mouseWheelZoom: false, // 禁止滚轮缩放
        doubleClickZoom: false, // 禁止双击缩放
        pinchZoom: false, // 禁止触摸捏合缩放
        keyboard: false, // 禁止键盘 +/- 缩放
        dragPan: false, // 保留拖拽平移(可根据需求关闭)
        // 若想完全禁止所有平移,可设置 dragPan: false
      }),
    })

最后呈现的就是一个带有阴影的矢量地图,可看做是一个简单的3D处理。

屏幕截图 2026-04-24 164335.png