MapLibre GL JS第63课:动画化标记

📌 学习目标

  • 掌握动画化标记的实现方法
  • 理解相关API的使用
  • 能够独立完成类似功能开发

🎯 核心概念

通过在每帧更新标记位置来动画化标记。

💻 完 整 代 码

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Animate a marker</title>
    <meta property="og:description" content="通过在每一帧更新位置来动画化标记的位置。" />
    <meta property="og:created" content="2006-06-25" />
    <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>
<div id="map"></div>
<script>
    const map = new maplibregl.Map({
        container: 'map',
        style: 'https://demotiles.maplibre.org/style.json',
        center: [0, 0],
        zoom: 2
    });

    const marker = new maplibregl.Marker();

    function animateMarker(timestamp) {
        const radius = 20;

        // 根据动画时间戳将数据更新到新位置。
        // 表达式 `timestamp / 1000` 中的除数控制动画速度。
        marker.setLngLat([
            Math.cos(timestamp / 1000) * radius,
            Math.sin(timestamp / 1000) * radius
        ]);

        // 确保将其添加到地图。如果已经添加,调用此方法是安全的。
        marker.addTo(map);

        // 请求动画的下一帧。
        requestAnimationFrame(animateMarker);
    }

    // 开始动画。
    requestAnimationFrame(animateMarker);
</script>
</body>
</html>

🔍 代码解析

1. 初始化地图

使用 new maplibregl.Map() 创建地图实例,配置了以赤道为中心的全球视图。

2. 关键配置项

  • requestAnimationFrame: 浏览器原生动画API,实现60fps流畅动画
  • Math.cos/sin: 使用三角函数计算圆形运动轨迹
  • timestamp: 动画时间戳,用于计算当前位置
  • setLngLat(): 更新标记位置

⚙️ 参数说明

参数类型必填说明
radiusnumber圆形运动半径(度数)
speednumber动画速度控制(timestamp除数)
timestampnumberrequestAnimationFrame传入的时间戳

🎨 效果说明

在这里插入图片描述

运行代码后,地图显示全球视图,标记以20度为半径围绕地图中心(0, 0)做匀速圆周运动。动画平滑流畅,标记位置每帧更新一次。

💡 常 见 问 题

Q1: 动画不流畅?
A: 检查以下几点:

  1. 确认使用requestAnimationFrame而非setInterval
  2. 减少每一帧的计算复杂度
  3. 避免在动画回调中进行DOM操作

Q2: 如何停止动画?
A: 使用cancelAnimationFrame停止动画:

const animationId = requestAnimationFrame(animateMarker);

// 停止动画
cancelAnimationFrame(animationId);

Q3: 如何实现其他运动轨迹?
A: 修改位置计算逻辑:

// 直线运动
marker.setLngLat([
    startLng + (endLng - startLng) * progress,
    startLat + (endLat - startLat) * progress
]);

// 椭圆运动
marker.setLngLat([
    Math.cos(timestamp / 1000) * radiusX,
    Math.sin(timestamp / 1000) * radiusY
]);

📝 练习任务

  1. 基础练习:修改运动半径和速度,观察动画效果变化
  2. 进阶挑战:实现直线运动动画
  3. 拓展思考:如何实现带缓动效果的动画?
  4. 综合实践:创建一个模拟车辆行驶轨迹的动画

🌟 最佳实践

  1. 动画流畅性: 使用requestAnimationFrame而非setInterval
  2. 性能优化: 避免在动画回调中进行DOM操作和复杂计算
  3. 资源管理: 及时取消不再需要的动画,避免内存泄漏
  4. 帧率控制: 考虑使用时间增量而非固定间隔
  5. 用户体验: 提供开始/暂停控制,允许用户控制动画

🔗 延伸阅读


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丷丩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值