LBS 开发微课堂|全新track轨迹插件:轻松实现轨迹可视化效果

为了让广大开发者更深入地了解百度地图开放平台的技术能力

轻松掌握满满的技术干货

更加简单地接入位置服务

我们特别推出了

位置服务(LBS)开发微课堂

系列技术案例

第八期的主题是

如何借助百度地图 track轨迹插件实现轨迹可视化效果

在当今数字化时代,地理信息的动态展示已成为各类应用中提升用户体验的重要功能。

在这其中,轨迹信息的展示尤为重要,它不仅能够直观呈现移动对象的路径,还能为各行业提供有力的数据支持。

轨迹信息的应用场景非常广泛,涵盖了物流、智慧城市、旅游、安全管理及农业等多个领域。例如,物流企业可通过轨迹信息优化配送路线,降低运输成本;智慧城市则可利用其监控公共交通和市政服务车辆的运行效率;旅游行业能够借助轨迹信息为用户提供动态路线演示,提升旅游体验;安全管理部门可通过轨迹分析优化巡逻路径,提高管理效率;农业领域则能利用轨迹信息监测农用机械作业,提高农业生产效率。

近期,百度地图JavaScript API全新推出了"track轨迹插件",能够支持开发者在网页中轻松实现对轨迹路径的动态演示。

那么这一款插件具有哪些技术亮点,具体的逻辑实现过程又是怎么样的呢?让我们一起来看看吧!

1.技术亮点

全新推出的"track轨迹插件"具有如下技术亮点:

  • 支持多种轨迹形式: 为开发者提供了轨迹回放实时轨迹两大核心功能,帮助用户精准还原历史轨迹,实时掌握目标位置,让位置数据更加生动直观。
  • 高效的数据处理: 支持大规模轨迹数据的高效处理,确保在复杂路径和大量数据的情况下,轨迹运动的展示依然流畅。
  • 灵活的自定义能力: 开发者可以根据需求自定义轨迹的样式、速度、动画效果等,满足不同应用场景的个性化需求。
  • 丰富的控制接口: 提供了播放、暂停、停止、重置、事件等多种控制接口,方便开发者实现对轨迹的精确控制。
  • 平滑的动画效果: 通过插值算法,确保对象在路径上的移动平滑自然,提升用户的视觉体验。

2.技术实现

2.1 轨迹系统架构

百度地图的"track轨迹插件"基于JSAPI框架,使用线图层能力。整体系统分为顶层管理、轨迹管理、轨迹点三个部分。功能结构清晰简洁,支持自定义多种可视化效果。

顶层管理

  • MapContentManager:轨迹功能的核心管理器,负责调度 Track
  • Track:轨迹管理的核心类,提供轨迹的增删、更新功能。
  • Map:JSAPI地图实例,与 Track 进行交互,渲染轨迹。
  • RAFController:采用 requestAnimationFrame 控制轨迹动画更新。

轨迹管理:

  • RoadTrack:核心轨迹基类,管理轨迹点,并提供轨迹渲染和动画控制能力。
  • LocalTrackNavTrackLiveTrackRoadTrack 的子类,分别对应本地轨迹、导航轨迹和实时轨迹。

轨迹点类型:

  • TrackPoint:轨迹点的基类。
  • TrackLine:由多个 TrackPoint 组成的轨迹线。
  • MarkerPoint:带有标记功能的轨迹点。
  • MovePoint:移动的轨迹点,用于表示轨迹回放,轨迹增长过程点的实时变化,可以使用Marker、GroundPoint、3D模型等多种类型点,支持自定义。
  • StaticPoint:静态轨迹点,适用于固定标记。

2.2 轨迹核心逻辑实现

此次推出的轨迹插件,支持全程匀速播放,也支持依据实际速度等比例转换成动画时间进行回放(需要轨迹点包含时间数据)。

要想实现丝滑的轨迹动画效果,通常需要以下步骤:

步骤1:初始化时计算总距离、平均动画速度和实际平均速度。

<math xmlns="http://www.w3.org/1998/Math/MathML"> d i s t a n c e s = ∑ 0 < i < t r a c k P o i n t s . l e n g t h d i s t a n c e ( P i , P i + 1 ) distances = \sum_{ \begin{subarray}{l} 0<i<trackPoints.length \end{subarray}} distance(P_i, P_{i+1}) </math>distances=∑0<i<trackPoints.lengthdistance(Pi,Pi+1)

<math xmlns="http://www.w3.org/1998/Math/MathML"> a n i m e V = d i s t a n c e s / d u r a t i o n animeV = distances/duration </math>animeV=distances/duration

<math xmlns="http://www.w3.org/1998/Math/MathML"> r e a l V = d i s t a n c e s / t i m e realV = distances/time </math>realV=distances/time

步骤 2:为每个轨迹段计算详细信息。

根据速度模式和轨迹点的时间戳,分为两种情况处理:

  • 实际速度模式:计算两个轨迹点间每段轨迹的实际时间、实际速度、持续时间(基于实际时间和总动画时间的比例)和动画速度(基于该段的距离和持续时间),速度计算公式同步骤1。
  • 匀速模式: 使用平均动画速度,计算每段轨迹的动画持续时间(基于该段的距离和总距离的比例)。

然后将这些信息以及角度存入分段轨迹数据中。

步骤 3:动画效果实现。

  • 计算动画的帧数
javascript 复制代码
// 这里的 16.6ms 约等于 60FPS 的帧率(1000ms/60 ≈ 16.6ms)
// frames 表示动画的总帧数,确保动画符合设定的 duration
let frames = Math.floor(this.animationOptions.duration / 16.6);
  • 获取地图当前状态
arduino 复制代码
// getHeading():获取地图当前旋转角度
let lastRotationAngle = this.map.getHeading();

// getTilt():获取地图当前倾斜角度
let lastTiltAngle = this.map.getTilt();

// getCenter():获取地图当前中心点(经纬度)
let lastCenter = this.map.getCenter();
  • 计算总差值和每一帧插值
ini 复制代码
// 计算目标值与当前值之间的差值,后续用于逐帧插值计算

let diffTiltAngle = tiltAngle - lastTiltAngle;
let diffX = center.lng - lastCenter.lng;
let diffY = center.lat - lastCenter.lat;

for (let i = 0; i < frames; i++) {
    // 使用贝塞尔曲线 (cubicBezier) 计算缓动曲线,确保动画平滑自然
    let cubicBezierValue = cubicBezier(
        this.animationControlPoint[0],
        this.animationControlPoint[1],
        this.animationControlPoint[2],
        this.animationControlPoint[3],
        (i + 1) / frames,
    );

    // 避免数值误差导致不必要的动画
    if (Math.abs(diffRotationAngle) > 5) {
        this.rotationAngleStep[i] = angle2MapAngle(lastRotationAngle + diffRotationAngle * cubicBezierValue.y);
    }

    // 避免数值误差导致不必要的动画
    if (Math.abs(diffTiltAngle) > 2) {
        this.tiltAngleStep[i] = diffTiltAngle * cubicBezierValue.y + lastTiltAngle;
    }
    
    // 避免数值误差导致不必要的动画
    if (Math.abs(diffX) > 0.000001 || Math.abs(diffY) > 0.000001) {
        let lat =  lastCenter.lat + diffY *  cubicBezierValue.y;
        let lng = lastCenter.lng + diffX * cubicBezierValue.y;
        this.centerStep[i] = new BMapGL.Point(lng, lat);
    }

    // 最终补充关键帧,确保动画最终帧准确达到目标值
    if (Math.abs(diffRotationAngle) > 5) {
        this.rotationAngleStep.push(rotationAngle);
    }
   
    if (Math.abs(diffX) > 0.000001 || Math.abs(diffY) > 0.000001) {
        this.tiltAngleStep.push(tiltAngle);
    }
    this.centerStep.push(center);

3.示例和效果展示

3.1 示例代码

首先创建轨迹图层,配置轨迹图层可视化效果。

php 复制代码
// 创建Track实例
const track = new Track.View(map, {
    cruiseOptions:{
        cruisePosition: [250,150],
        cruiseLookAt: -90
    },
    lineLayerOptions: {
        style: {
            strokeWeight: 8,
            strokeLineJoin: 'round',
            strokeLineCap: 'round'
        },
    }
});

然后创建轨迹实例,配置轨迹可视化效果。

php 复制代码
// 创建轨迹
const trackRoad = new Track.LocalTrack({
    trackPath: trackData,
    duration: trackData.length / 3,
    style: {
        traceDisappear: true,
        sequence: true,
        marginLength: 32,
        arrowColor: '#fff',
        strokeTextureUrl: './images/down.png',
        strokeTextureWidth: 64,
        strokeTextureHeight: 32,
        traceColor: [27, 142, 236]
    },
    linearTexture: [[0, '#f45e0c'], [0.5, '#f6cd0e'], [1, '#2ad61d']],
    gradientColor: colorOffset
});

最后将轨迹添加到轨迹图层中。

scss 复制代码
// 添加轨迹
track.addTrackLine(trackRoad);

3.2 效果展示

轨迹回放

在线轨迹

借助百度地图JS API的"track轨迹插件",开发者可以为用户提供动态、直观的位置信息展示,满足多样化的业务需求。

获取更多关于实时轨迹功能的具体实现示例,请您访问百度地图JS API示例中心,帮助您快速上手开发。

示例中心地址:lbs.baidu.com/jsdemo.htm#...

百度地图会持续推出功能更加丰富的可视化插件,敬请期待!

·END·

你还想了解哪些技术内容?

快来评论区留言告诉我们吧!

相关推荐
zrhsmile2 分钟前
Vue从入门到荒废-单向绑定
javascript·vue.js·ecmascript
百锦再4 分钟前
React编程的核心概念:发布-订阅模型、背压与异步非阻塞
前端·javascript·react.js·前端框架·json·ecmascript·html5
thinkQuadratic8 分钟前
scss预处理器对比css的优点以及基本的使用
前端·css·scss
yuluo_YX29 分钟前
使用 Spring AI Aliabab Module RAG 构建 Web Search 应用
前端·人工智能·spring
冴羽30 分钟前
SvelteKit 最新中文文档教程(16)—— Service workers
前端·javascript·svelte
Hongwen100140 分钟前
寒冬之中的AI创意实验:48小时左右从零打造吉卜力风格AI绘图网站
前端·后端·cursor
小鸭呱呱呱1 小时前
【CSS】- 表单控件的 placeholder 如何控制换行显示?
前端·javascript·css·深度学习·面试·职场和发展·html
小浣熊喜欢揍臭臭1 小时前
vue+webpack5(高级配置)
前端·javascript·vue.js
Bigger1 小时前
Tauri(十七)—— 安装包和应用包的区别
前端·app·mac
茉莉蜜茶only1 小时前
【前端实习岗位】淘天集团2026届春季实习生招聘
前端·招聘