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实践课程系列的一部分,欢迎关注收藏

相关推荐
半个烧饼不加肉2 小时前
JS 底层探究--上下文
开发语言·javascript·ecmascript
无风听海3 小时前
PKCE 的 S256 算法深度剖析:从协议设计到密码学原理
javascript·网络·算法·密码学
小新1103 小时前
vue实战项目 计算器
前端·javascript·vue.js
老毛肚3 小时前
jeecgboot vue 路由 拆分01
前端·javascript·typescript
西部荒野子3 小时前
Zustand 状态管理规范:别让轻量状态变成隐形通知风暴
前端·javascript
之歆4 小时前
Day04_ES6完全指南:从入门到精通的现代化JavaScript开发
前端·javascript·es6
触底反弹4 小时前
从数据结构到 Prompt 设计:前端工程师的 AI 时代进阶指南
javascript·人工智能·python
橘猫走江湖4 小时前
前端项目如何做 vibe coding
javascript·vue.js·架构