MapLibre GL JS第38课:根据缩放级别改变建筑颜色

📌 学习目标

  • 掌握根据缩放级别改变建筑颜色的实现方法
  • 理解相关API的使用
  • 能够独立完成类似功能开发

🎯 核心概念

根据缩放级别改变建筑颜色。

💻 完 整 代 码

代码示例

js 复制代码
const map = new maplibregl.Map({
    container: 'map',
    style: 'https://tiles.openfreemap.org/styles/bright',
    center: [-90.73414, 14.55524],
    zoom: 13
});

map.on('load', () => {
    map.setPaintProperty('building-top', 'fill-color', [
        'interpolate',
        ['exponential', 0.5],
        ['zoom'],
        15,
        '#e2714b',
        22,
        '#eee695'
    ]);

    map.setPaintProperty('building-top', 'fill-opacity', [
        'interpolate',
        ['exponential', 0.5],
        ['zoom'],
        15,
        0,
        22,
        1
    ]);
});

document.getElementById('zoom').addEventListener('click', () => {
    map.zoomTo(19, {duration: 9000});
});

代码示例

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Change building color based on zoom level</title>
    <meta property="og:description" content="使用插值表达式缓入建筑物图层,并在两种颜色之间平滑过渡。" />
    <meta property="og:created" content="2023-06-27" />
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.css' />
    <script src='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.js'></script>
    <style>
        body { margin: 0; padding: 0; }
        html, body, #map { height: 100%; }
    </style>
</head>
<body>
<style>
    #zoom {
        display: block;
        position: absolute;
        top: 20px;
        left: 50%;
        transform: translate(-50%);
        width: 50%;
        height: 40px;
        padding: 10px;
        border: none;
        border-radius: 3px;
        font-size: 12px;
        text-align: center;
        color: #fff;
        background: #ee8a65;
    }
</style>
<div id="map"></div>
<button id="zoom">Zoom to buildings</button>
<script>
    const map = new maplibregl.Map({
        container: 'map',
        style: 'https://tiles.openfreemap.org/styles/bright',
        center: [-90.73414, 14.55524],
        zoom: 13
    });

    map.on('load', () => {
        map.setPaintProperty('building-top', 'fill-color', [
            'interpolate',
            ['exponential', 0.5],
            ['zoom'],
            15,
            '#e2714b',
            22,
            '#eee695'
        ]);

        map.setPaintProperty('building-top', 'fill-opacity', [
            'interpolate',
            ['exponential', 0.5],
            ['zoom'],
            15,
            0,
            22,
            1
        ]);
    });

    document.getElementById('zoom').addEventListener('click', () => {
        map.zoomTo(19, {duration: 9000});
    });
</script>
</body>
</html>

🔍 代码解析

初始化地图

使用 new maplibregl.Map() 创建地图实例,配置基本参数。本示例的核心特色是展示如何根据缩放级别动态改变建筑物颜色和透明度。

关键配置项

  • container: 地图容器的 DOM 元素 ID
  • style : 使用 MapLibre 官方样式 https://tiles.openfreemap.org/styles/bright
  • center : 地图初始中心点 [-90.73414, 14.55524](洪都拉斯附近)
  • zoom: 初始缩放级别为 13,显示城市级别视图

插值表达式配置

javascript 复制代码
map.on('load', () => {
    map.setPaintProperty('building-top', 'fill-color', [
        'interpolate',
        ['exponential', 0.5],
        ['zoom'],
        15,
        '#e2714b',
        22,
        '#eee695'
    ]);

    map.setPaintProperty('building-top', 'fill-opacity', [
        'interpolate',
        ['exponential', 0.5],
        ['zoom'],
        15,
        0,
        22,
        1
    ]);
});

缩放动画按钮

javascript 复制代码
document.getElementById('zoom').addEventListener('click', () => {
    map.zoomTo(19, {duration: 9000});
});

⚙️ 参数说明

参数 类型 必填 默认值 说明
container string - 地图容器元素的 ID
style string/object - 地图样式 URL 或内联样式对象
center number, number [0, 0] 初始中心点坐标,格式为 [经度, 纬度]
zoom number 0 初始缩放级别,范围 0-22

interpolate 表达式

参数 类型 说明
type string 插值类型:linearexponential
base number 指数插值的底数(仅 exponential 类型需要)
input expression 输入值(通常是 ['zoom']
stop1 number 第一个停止点的输入值
output1 any 第一个停止点的输出值
stop2 number 第二个停止点的输入值
output2 any 第二个停止点的输出值

🎨 效果说明

运行代码后,页面显示一个交互式地图,建筑物颜色和透明度随缩放级别变化:

  • 缩放级别 15 以下 : 建筑物完全透明(fill-opacity: 0
  • 缩放级别 15-22 : 建筑物从透明渐变为完全不透明,颜色从橙色(#e2714b)渐变为浅黄色(#eee695
  • 缩放级别 22 以上: 建筑物完全不透明,显示浅黄色

页面顶部有一个 "Zoom to buildings" 按钮,点击后会在9秒内平滑缩放到级别19,可以清楚看到建筑物颜色渐变效果。

💡 常 见 问 题

Q1: 插值表达式的工作原理是什么?

A: 插值表达式根据输入值(如缩放级别)在指定的停止点之间进行插值计算。linear 插值是线性的,exponential 插值是非线性的,底数越大变化越陡峭。

Q2: 可以使用哪些插值类型?

A: MapLibre 支持 linear(线性插值)和 exponential(指数插值)两种类型。线性插值变化均匀,指数插值在高缩放级别变化更快。

Q3: 如何添加更多停止点?

A: 在插值表达式中添加更多的 stop, output 对即可。例如:

javascript 复制代码
['interpolate', ['linear'], ['zoom'], 10, '#fff', 15, '#ccc', 20, '#000']

Q4: 插值表达式可以用于哪些属性?

A: 大多数 paint 属性都支持插值表达式,包括颜色、透明度、宽度等。

📝 练习任务

  1. 基础练习:修改颜色值,尝试不同的颜色渐变效果
  2. 进阶挑战:添加更多停止点,实现更复杂的颜色变化
  3. 拓展思考:如何根据缩放级别改变建筑物的高度(3D效果)?

🌟 最佳实践

  1. 表达式复用: 将复杂的表达式提取为变量,便于维护
  2. 性能优化 : 使用 exponential 插值可以在高缩放级别提供更好的性能
  3. 视觉设计: 确保颜色渐变在整个缩放范围内都清晰可见
  4. 测试验证: 在不同缩放级别测试效果,确保过渡平滑
  5. 文档说明: 添加注释说明插值表达式的含义和预期效果
  6. 用户体验: 提供缩放动画按钮帮助用户观察效果变化

🔗 延伸阅读


本文是MapLibre GL JS实践课程系列的一部分,欢迎关注收藏

相关推荐
kyriewen1 小时前
用了半年 Claude Code 后,我尝试关掉它写了一周代码——结果比想象中严重
前端·javascript·ai编程
山河木马3 小时前
矩阵专题0-webGL中的矩阵
javascript·webgl·计算机图形学
Asize3 小时前
多模态生图:从 Vite 工程化到前端调用 Qwen Image
javascript·人工智能·后端
陳陈陳3 小时前
从Token到Embedding:一篇文章搞懂大模型的「文字数学变形记」
前端·javascript·ai编程
用户938515635073 小时前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
橘子星3 小时前
LLM 无状态架构实践:从原理到代码落地
前端·javascript·人工智能
To_OC4 小时前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法
风止何安啊5 小时前
网课倍速痛点解决:一套前端代码实现自由控速播放器
前端·javascript·node.js
光影少年7 小时前
原生DOM操作在React 中的注意事项
前端·javascript·react.js
糖拌西瓜皮7 小时前
Node.js核心模块实战:文件、路径、HTTP与流处理
javascript·node.js