在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处理。