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

相关推荐
泯泷5 小时前
那段文字是谁删的?Yjs 14 正式版之前,一套删除归属方案的实现与边界
前端·javascript·算法
hold?fish:palm5 小时前
34 合并K个升序链表
javascript·算法·链表
幸运小圣8 小时前
PointerEvent 常用属性与事件整理【JavaScript】
开发语言·javascript·ecmascript
志尊宝9 小时前
Vue3 零基础每日笔记(038):亲手封装 useDebounceFn 与 useThrottleFn——高频事件的流量阀
前端·javascript·vue·html·vue3
默_笙11 小时前
🚅 地铁的"回头路、存档点与人工闸机"(下):LangGraph 的循环、持久化与中断
前端·javascript
flash俊杰11 小时前
Zod Schema 驱动的 IPC 契约:从入参校验到状态机一致性的三层防御
javascript·typescript
一条溺水的鱼14 小时前
一次讲透 JS 原型链 —— prototype、__proto__ 和 constructor 到底啥关系
javascript
三乐22814 小时前
一文搞懂 JS 事件流:捕获、冒泡、事件委托
javascript·html
愛芳芳16 小时前
基于 Electron + Vue3 的仿 PC 微信客户端项目实战
前端·javascript·css·elementui·typescript·electron·vue
阿虎儿17 小时前
论 JavaScript 的怪异之处
javascript