添加自定义样式图层
使用自定义样式图层渲染自定义WebGL内容;
<!DOCTYPE html>
<html lang="en">
<head>
<title>添加自定义样式图层</title>
<meta property="og:description" content="使用自定义样式图层渲染自定义WebGL内容" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.css' />
<script src='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.js'></script>
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = new maplibregl.Map({
container: 'map',
zoom: 3,
center: [7.5, 58],
style: 'https://demotiles.maplibre.org/style.json',
canvasContextAttributes: {antialias: true} // 创建带MSAA抗锯齿的gl上下文,使自定义图层也能抗锯齿
});
// 创建自定义样式图层以实现WebGL内容
const highlightLayer = {
id: 'highlight',
type: 'custom',
// 当图层添加到地图时调用的方法
// 在https://maplibre.org/maplibre-gl-js/docs/API/中查找StyleImageInterface
onAdd (map, gl) {
// 为顶点着色器创建GLSL源代码
const vertexSource = `#version 300 es
uniform mat4 u_matrix;
in vec2 a_pos;
void main() {
gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);
}`;
// 为片段着色器创建GLSL源代码
const fragmentSource = `#version 300 es
out highp vec4 fragColor;
void main() {
fragColor = vec4(1.0, 0.0, 0.0, 0.5);
}`;
// 创建顶点着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
// 创建片段着色器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
// 将两个着色器链接到WebGL程序中
this.program = gl.createProgram();
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
this.aPos = gl.getAttribLocation(this.program, 'a_pos');
// 定义要在自定义样式图层中渲染的三角形顶点
const helsinki = maplibregl.MercatorCoordinate.fromLngLat({
lng: 25.004,
lat: 60.239
});
const berlin = maplibregl.MercatorCoordinate.fromLngLat({
lng: 13.403,
lat: 52.562
});
const kyiv = maplibregl.MercatorCoordinate.fromLngLat({
lng: 30.498,
lat: 50.541
});
// 创建并初始化WebGLBuffer以存储顶点和颜色数据
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
helsinki.x,
helsinki.y,
berlin.x,
berlin.y,
kyiv.x,
kyiv.y
]),
gl.STATIC_DRAW
);
},
// 在每一帧动画上触发的方法
render (gl, args) {
gl.useProgram(this.program);
gl.uniformMatrix4fv(
gl.getUniformLocation(this.program, 'u_matrix'),
false,
args.defaultProjectionData.mainMatrix
);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.enableVertexAttribArray(this.aPos);
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, 0, 0);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
}
};
// 将自定义样式图层添加到地图
map.on('load', () => {
map.addLayer(highlightLayer, 'crimea-fill');
});
</script>
</body>
</html>