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

相关推荐
满栀5851 天前
原生JS + ECharts 多图表可视化实战:从业务实现到工程化优化
开发语言·javascript·echarts
sugar__salt1 天前
Vue3 自定义指令与插槽(Slot)技术详解
前端·javascript·vue.js·前端框架·vue
Hilaku1 天前
前端真的比后端简单吗?
前端·javascript·程序员
默_笙1 天前
🍔 我用 React 写了一个 TodoList,终于搞懂了"状态该放谁家"
前端·javascript
A24207349301 天前
Vue.js 初学者注意事项与项目开发实践指南
前端·javascript·vue.js
dllmayday1 天前
Bootstrap三开关样式
前端·javascript·bootstrap
带娃的IT创业者1 天前
PostHog 的 TypeScript 原生移植:一场开源产品工程化的自我革命
javascript·typescript·开源·开源软件·posthog·技术重构
FogLetter2 天前
当JavaScript学会“分身术”:异步编程的进化简史
前端·javascript·面试
java1234_小锋2 天前
Vue3+Vite简介以及构建第一个HelloWorld实例
前端·javascript·vue.js·vite
天天鸭2 天前
5 万处中文的老项目实现国际化,如何用架构思维完成改造?
前端·javascript·架构