当前位置: 首页 > news >正文

OpenLayers常用控件 -- 章节八:地图动画控件教程

前言

地图动画是现代Web地图应用中提升用户体验的重要手段。通过平滑的动画过渡,用户可以更直观地感受地图视图的变化过程,无论是位置跳转、缩放变化还是旋转操作。本文将详细介绍OpenLayers中的动画系统,包括基础动画、缓动函数、自定义动画效果等内容,帮助开发者为地图应用添加生动的交互体验。

项目结构分析

<template><!--地图挂载dom--><div id="map"><div class="MapTool"><el-row><el-button type="primary" @click.stop.prevent="rotateLocation">旋转定位</el-button><el-button type="success" @click.stop.prevent="elasticLocation">弹性定位</el-button><el-button type="info" @click.stop.prevent="reboundLocation">反弹定位</el-button><el-button type="warning" @click.stop.prevent="flyLocation">飞行定位</el-button><el-button type="danger" @click.stop.prevent="aroundRotate">围绕旋转</el-button></el-row></div></div>
</template>

模板结构详解:

  • 地图容器: id="map" 作为地图挂载点
  • 动画工具栏: .MapTool 包含五种不同类型的动画按钮
  • 动画分类: 包括旋转、弹性、反弹、飞行和围绕旋转五种动画效果
  • 事件绑定: 每个按钮都绑定了对应的动画方法

依赖引入详解

//引入依赖
import {Map, View} from 'ol'
import {OSM} from 'ol/source'
import TileLayer from 'ol/layer/Tile'
import {defaults as defaultControls} from 'ol/control.js';
import {easeIn, easeOut} from 'ol/easing';
import {fromLonLat} from 'ol/proj';

核心依赖说明:

基础组件
  • Map, View: OpenLayers地图和视图核心组件
  • OSM, TileLayer: 底图数据源和图层组件
动画相关
  • easeIn, easeOut: OpenLayers内置的缓动函数
  • easeIn: 缓入效果,动画开始慢,逐渐加速
  • easeOut: 缓出效果,动画开始快,逐渐减速
坐标处理
  • fromLonLat: 坐标转换函数,将经纬度坐标转换为地图投影坐标

全局变量定义

var beijing;
var guangzhou;

全局坐标变量:

  • beijing: 北京坐标点,用于动画目标位置
  • guangzhou: 广州坐标点,用于动画目标位置和旋转中心

数据属性初始化

data() {return {map: null,  // 地图实例}
}

地图初始化与坐标设置

mounted() {//注意参考系beijing = fromLonLat([116.3898468017578, 39.91026292816486], "EPSG:4326");guangzhou = fromLonLat([113.24981689453125, 23.126468438108688], "EPSG:4326");//初始化地图this.map = new Map({target: 'map',//指定挂载dom,注意必须是idlayers: [new TileLayer({source: new OSM()//加载OpenStreetMap})], controls: defaultControls({zoom: false//禁用右上角缩放组件}),//地图控件//配置视图view: new View({center: [113.24981689453125, 23.126468438108688], //视图中心位置projection: "EPSG:4326", //指定投影zoom: 12,  //缩放到的级别})});
}

初始化分析:

1. 坐标转换处理
beijing = fromLonLat([116.3898468017578, 39.91026292816486], "EPSG:4326");
guangzhou = fromLonLat([113.24981689453125, 23.126468438108688], "EPSG:4326");

坐标转换说明:

  • fromLonLat: 将经纬度坐标转换为指定投影坐标系
  • 第一个参数: [经度, 纬度] 数组
  • 第二个参数: 目标投影坐标系,这里是 EPSG:4326
  • 注意: 虽然目标投影与源坐标相同,但这样写保证了代码的兼容性
2. 地图视图配置
view: new View({center: [113.24981689453125, 23.126468438108688], //视图中心位置projection: "EPSG:4326", //指定投影zoom: 12,  //缩放到的级别
})

视图参数:

  • center: 初始中心点设置为广州
  • projection: 使用WGS84地理坐标系
  • zoom: 初始缩放级别为12

五种动画效果详解

1. 旋转定位动画 (rotateLocation)

rotateLocation() {let view = this.map.getView();var center = view.getCenter();//视图动画渲染view.animate({//动画结束时的视图中心,即当前视图中心同目标视图中心连线的中心点center: [center[0],center[1]],rotation: Math.PI,//动画结束时的旋转角度,即180度easing: easeIn//按每一帧动画控制的动画速度,即开始缓慢并逐渐加快速度},{center: beijing,//动画结束时的视图中心rotation: 2 * Math.PI,//动画结束时的旋转角度,即360度回正easing: easeOut//按每一帧动画控制的动画速度,即开始快速并逐渐减速});
}

动画分解分析:

第一阶段动画
{center: [center[0], center[1]],  // 保持当前中心点rotation: Math.PI,               // 旋转180度easing: easeIn                   // 缓入效果
}

效果说明:

  • 中心点: 保持在当前位置不变
  • 旋转角度: Math.PI 弧度 = 180度
  • 缓动效果: easeIn 让旋转开始慢,逐渐加速
第二阶段动画
{center: beijing,      // 移动到北京rotation: 2 * Math.PI, // 旋转360度回正easing: easeOut       // 缓出效果
}

效果说明:

  • 位置移动: 从当前位置移动到北京
  • 旋转角度: 2π 弧度 = 360度,完成一个完整旋转
  • 缓动效果: easeOut 让动画开始快,逐渐减速

2. 弹性定位动画 (elasticLocation)

elasticLocation() {// 弹性伸缩值function elastic(t) {//函数-10*sin(t-0.075)**t*t+1return Math.pow(2, -10 * t) * Math.sin((t - 0.075) * (2 * Math.PI) / 0.3) + 1;}let view = this.map.getView();view.animate({center: beijing,///动画结束时的视图中心duration: 2000,//动画的持续时间(以毫秒为单位)easing: elastic//按每一帧动画控制的动画持续时间函数});
}

弹性函数详解:

数学公式分析
function elastic(t) {return Math.pow(2, -10 * t) * Math.sin((t - 0.075) * (2 * Math.PI) / 0.3) + 1;
}

函数组成:

  • Math.pow(2, -10 * t): 指数衰减函数,控制弹性振幅逐渐减小
  • Math.sin((t - 0.075) * (2 * Math.PI) / 0.3): 正弦振荡函数,产生弹性效果
  • t参数: 动画进度,范围0-1
  • 返回值: 弹性缓动的位置值

视觉效果:

  • 动画会有弹簧般的震荡效果
  • 逐渐收敛到目标位置
  • 类似弹性球落地后的弹跳效果

3. 反弹定位动画 (reboundLocation)

reboundLocation() {// 反弹值function bounce(t) {var s = 7.5625, p = 2.75, l;if (t < (1 / p)) {l = s * t * t;} else {if (t < (2 / p)) {t -= (1.5 / p);l = s * t * t + 0.75;} else {if (t < (2.5 / p)) {t -= (2.25 / p);l = s * t * t + 0.9375;} else {t -= (2.625 / p);l = s * t * t + 0.984375;}}}return l;}let view = this.map.getView();view.animate({center: guangzhou,///动画结束时的视图中心duration: 2000,//动画的持续时间(以毫秒为单位)easing: bounce//按每一帧动画控制的动画持续时间函数});
}

反弹函数详解:

分段函数结构
function bounce(t) {var s = 7.5625, p = 2.75, l;// 四个阶段的反弹效果
}

参数说明:

  • s = 7.5625: 反弹强度系数
  • p = 2.75: 反弹周期参数
  • t: 动画进度(0-1)

分段逻辑:

  1. 第一段 (t < 1/2.75): 主要反弹阶段
  2. 第二段 (t < 2/2.75): 第二次较小反弹
  3. 第三段 (t < 2.5/2.75): 第三次更小反弹
  4. 第四段 (其余): 最后的微小反弹

视觉效果:

  • 模拟球体从高处落下的反弹效果
  • 反弹高度逐次递减
  • 最终稳定在目标位置

4. 飞行定位动画 (flyLocation)

flyLocation() {let view = this.map.getView();var duration = 2000;//动画的持续时间(以毫秒为单位)var zoom = view.getZoom();//动画完成的回调函数function callback(complete) {console.log("动画完成" + complete)}//第一个动画view.animate({center: guangzhou,duration: duration}, callback);//第二个动画view.animate({zoom: zoom - 1,duration: duration / 2}, {zoom: zoom,duration: duration / 2}, callback);
}

飞行动画详解:

并行动画设计
//第一个动画 - 位置移动
view.animate({center: guangzhou,   // 目标位置duration: duration   // 持续时间2000ms
}, callback);//第二个动画 - 缩放变化
view.animate({zoom: zoom - 1,      // 先缩小一级duration: duration / 2  // 前半段1000ms
}, {zoom: zoom,          // 再恢复原始缩放duration: duration / 2  // 后半段1000ms
}, callback);

动画组合效果:

  1. 位置动画: 平移到广州,持续2秒
  2. 缩放动画: 同时进行两阶段缩放
  • 阶段1: 缩小一级(1秒)
  • 阶段2: 恢复原缩放(1秒)

飞行效果模拟:

  • 类似飞机起飞时的视觉效果
  • 先升高(缩小)再降落(放大)
  • 同时完成位置移动
回调函数机制
function callback(complete) {console.log("动画完成" + complete)
}

回调参数:

  • complete: 布尔值,表示动画是否完整执行完毕
  • 用途: 可以在动画完成后执行额外逻辑

5. 围绕旋转动画 (aroundRotate)

aroundRotate() {let view = this.map.getView();var rotation = view.getRotation();view.animate(//第一个过程{rotation: rotation + Math.PI,//第一次动画旋转角度anchor: guangzhou,//自旋的中心点easing: easeIn////按每一帧动画控制的动画速度,即开始缓慢并逐渐加快速度},//第二个过程{rotation: rotation + 2 * Math.PI,//动画结束时的旋转角度,即360度回正anchor: guangzhou,// 旋转中心点easing: easeOut///按每一帧动画控制的动画速度,即开始快速并逐渐减速});
}

围绕旋转详解:

旋转中心概念
anchor: guangzhou,//自旋的中心点

anchor参数说明:

  • 功能: 指定旋转的锚点/中心点
  • 坐标: 使用广州的地理坐标
  • 效果: 视图围绕广州这个点进行旋转
两阶段旋转
//第一个过程
{rotation: rotation + Math.PI,  // 旋转180度anchor: guangzhou,             // 围绕广州旋转easing: easeIn                 // 缓入效果
}//第二个过程  
{rotation: rotation + 2 * Math.PI, // 继续旋转到360度anchor: guangzhou,                 // 继续围绕广州旋转easing: easeOut                    // 缓出效果
}

视觉效果:

  • 地图围绕广州点旋转360度
  • 分两个阶段,每阶段180度
  • 先加速后减速的流畅动画

OpenLayers动画系统深度分析

View.animate() 方法详解

view.animate(animationOptions, callback)
动画选项参数:
参数类型功能示例
centerArray目标中心点坐标[116.39, 39.91]
zoomNumber目标缩放级别10
rotationNumber目标旋转角度(弧度)Math.PI
anchorArray旋转锚点坐标[116.39, 39.91]
durationNumber动画持续时间(毫秒)2000
easingFunction缓动函数easeIn

内置缓动函数

OpenLayers提供了多种内置缓动函数:

import {easeIn, easeOut, inAndOut, linear, upAndDown} from 'ol/easing';
函数效果适用场景
linear匀速运动简单的直线移动
easeIn缓慢开始,逐渐加速启动效果
easeOut快速开始,逐渐减速停止效果
inAndOut先加速后减速平滑过渡
upAndDown先上升后下降弧形运动

实际应用扩展

1. 自定义缓动函数

methods: {// 自定义三次贝塞尔曲线缓动customEasing(t) {// 模拟CSS cubic-bezier(0.25, 0.46, 0.45, 0.94)return t * t * (3.0 - 2.0 * t);},// 使用自定义缓动customAnimation() {let view = this.map.getView();view.animate({center: beijing,duration: 1500,easing: this.customEasing});}
}

2. 动画队列管理

data() {return {map: null,animationQueue: [],isAnimating: false}
},methods: {// 添加动画到队列addAnimation(animationConfig) {this.animationQueue.push(animationConfig);this.processQueue();},// 处理动画队列processQueue() {if (this.isAnimating || this.animationQueue.length === 0) {return;}this.isAnimating = true;const config = this.animationQueue.shift();let view = this.map.getView();view.animate(config, (complete) => {this.isAnimating = false;if (complete) {this.processQueue(); // 继续下一个动画}});}
}

3. 动画状态监控

data() {return {map: null,animationProgress: 0,animationStatus: 'idle' // idle, running, paused}
},methods: {// 带进度监控的动画animateWithProgress(targetCenter) {let view = this.map.getView();const startTime = Date.now();const duration = 2000;const animate = () => {const elapsed = Date.now() - startTime;const progress = Math.min(elapsed / duration, 1);this.animationProgress = progress * 100;this.animationStatus = progress === 1 ? 'idle' : 'running';if (progress < 1) {requestAnimationFrame(animate);}};view.animate({center: targetCenter,duration: duration}, () => {this.animationStatus = 'idle';this.animationProgress = 100;});animate();}
}

4. 多视图同步动画

methods: {// 多个地图视图同步动画synchronizedAnimation() {const views = [this.map.getView()]; // 可以添加多个视图const targetCenter = beijing;const duration = 2000;views.forEach(view => {view.animate({center: targetCenter,duration: duration,easing: easeInOut});});}
}

核心API方法总结

View.animate() 核心参数:

参数类型默认值说明
centerArray当前中心目标中心点坐标
zoomNumber当前缩放目标缩放级别
rotationNumber当前旋转目标旋转角度(弧度)
anchorArraycenter旋转锚点
durationNumber1000动画时长(毫秒)
easingFunctioninAndOut缓动函数

常用数学常量:

常用数学常量:

常量角度等价用途
Math.PI3.14159...180°半圆旋转
2 * Math.PI6.28318...360°完整旋转
Math.PI / 21.5708...90°直角旋转
Math.PI / 40.7854...45°八分之一旋转

总结

本文详细介绍了OpenLayers中的地图动画系统,主要知识点包括:

  1. 基础动画: 学习了view.animate()方法的基本用法
  2. 缓动函数: 掌握了内置和自定义缓动函数的应用
  3. 组合动画: 理解了多阶段动画和并行动画的实现
  4. 旋转动画: 学习了围绕指定点旋转的技巧
  5. 实际应用: 提供了多种高级动画效果的实现方案

地图动画的核心价值在于:

  • 用户体验: 提供流畅自然的视觉过渡效果
  • 空间感知: 帮助用户理解地理位置之间的关系
  • 交互反馈: 让地图操作更加生动有趣
  • 专业品质: 提升应用的整体质量和用户满意度

掌握了这些动画技术,就可以为Web地图应用添加专业级的动态效果,创造出更加引人入胜的用户体验。无论是简单的位置跳转,还是复杂的3D飞行效果,都可以通过合理的动画设计来实现。


文章转载自:

http://Tu2yx9Rf.fkxkk.cn
http://tQ52PSBu.fkxkk.cn
http://LlZCmkLU.fkxkk.cn
http://GRKT5F5u.fkxkk.cn
http://KiFk4Pvo.fkxkk.cn
http://KxhAYLwr.fkxkk.cn
http://d6MuEpw4.fkxkk.cn
http://g5YzPCUF.fkxkk.cn
http://n7LLzjGZ.fkxkk.cn
http://VJmENvF2.fkxkk.cn
http://271UvVID.fkxkk.cn
http://VLRaLY31.fkxkk.cn
http://bXAB7cb9.fkxkk.cn
http://YtKidQnd.fkxkk.cn
http://MYKg1YO3.fkxkk.cn
http://UGk3aHSK.fkxkk.cn
http://IIHNTbtA.fkxkk.cn
http://tDHhhhPF.fkxkk.cn
http://7gdbbCF3.fkxkk.cn
http://oeO62xUl.fkxkk.cn
http://XENVhcCr.fkxkk.cn
http://sDp5C51J.fkxkk.cn
http://AJvM36LM.fkxkk.cn
http://NJkluoMb.fkxkk.cn
http://9O69UkEw.fkxkk.cn
http://ZvLuMmMV.fkxkk.cn
http://vwoYaccm.fkxkk.cn
http://iVQIaB9W.fkxkk.cn
http://LltKjIX6.fkxkk.cn
http://zAQaOJat.fkxkk.cn
http://www.dtcms.com/a/371756.html

相关文章:

  • 在 CI/CD 管道中集成人工智能 (AI)
  • 开源项目MusicGen技术详解
  • 【面向对象编程——多继承】
  • 算法题-哈希表01
  • 云平台面试内容(二)
  • Carlsson_HEAL-SWIN_A_Vision_Transformer_On_The_Sphere_CVPR_2024_paper_analysis
  • 微服务的保护方式以及Sentinel详解
  • 【jenkins】--安装部署
  • Vue 路由传参的四种方式
  • HTML 表格基础
  • CD76.【C++ Dev】AVL的模拟实现(1) 以左单旋为切口,分析旋转规律
  • 中国计算机发展史
  • LeetCode刷题记录----20.有效的括号(Easy)
  • 从voice和练习发声谈起
  • 5.python——数字
  • 数据化运营的工作流程
  • llama_factory 安装以及大模型微调
  • Linux | i.MX6ULL 搭建 Web 服务器(第二十章)
  • 量子電腦組裝之三
  • 适配器详细
  • GD32自学笔记:5.定时器中断
  • 前端三件套简单学习:HTML篇1
  • Android --- SystemUI 导入Android Studio及debug
  • 服务器为什么会选择暴雨?
  • Spring Boot + Apache Tika 从文件或文件流中提取文本内容
  • day26|学习前端之算法学习
  • 数据结构之二叉树(2)
  • Mac设置中的安全性缺少“任何来源”
  • 样式化你的 Next.js 应用:CSS 模块、Tailwind CSS 和全局样式
  • Qwen2.5-VL技术详解