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

鸿蒙运动健康实战:自定义定位箭头跟随手机方向旋转

告别系统蓝点实现高精度自定义定位箭头实时响应手机朝向为运动轨迹应用增添使用交互体验。完整源码SportTrackDemo在上一节中我们已经实现了运动轨迹记录、后台长时任务申请等功能。但系统默认的“我的位置”蓝点带有光圈。虽然可以自定义样式但是无法实现箭头跟随手机方向旋转。本文将手把手教你如何关闭系统定位图层用自定义 Marker 替换并通过传感器获取设备方向让箭头实时指向手机朝向。一、最终效果二、实现思路关闭系统定位图层setMyLocationEnabled(false)避免显示默认蓝点。自定义定位 Marker创建带箭头的 Marker锚点设为中心便于旋转。监听定位变化实时更新 Marker 的位置。监听方向传感器获取设备方位角0~360°0北顺时针。实时旋转调用marker.setRotation(angle)。三、核心代码实现3.1 在MapManager中添加自定义定位箭头管理// MapManager.etsprivatemyLocationMarker?:map.Marker;/** * 更新自定义定位箭头的位置和旋转角度 * param lat 纬度GCJ02 * param lng 经度GCJ02 * param rotation 旋转角度0~360°0正北 */asyncupdateMyLocationMarker(lat:number,lng:number,rotation?:number):Promisevoid{if(!this.myLocationMarker){constoptions:mapCommon.MarkerOptions{position:{latitude:lat,longitude:lng},icon:$r(app.media.ic_location_arrow),// 箭头图标anchorU:0.5,anchorV:0.5,flat:false,// 面对相机旋转效果明显clickable:false};this.myLocationMarkerawaitthis.mapController?.addMarker(options);}else{this.myLocationMarker.setPosition({latitude:lat,longitude:lng});}if(rotation!undefined){this.myLocationMarker.setRotation(rotation);}}setMyLocationRotation(rotation:number):void{this.myLocationMarker?.setRotation(rotation);}removeMyLocationMarker():void{this.myLocationMarker?.remove();this.myLocationMarkerundefined;}关键点anchorU/V: 0.5确保旋转中心在图标中心。flat: false使图标始终面向相机旋转效果清晰。如果你使用的是“圆点箭头”组合图标例如一个圆点旁边带箭头且将锚点设为 (0.5, 0.5) 中心点那么圆点必须位于图标的几何中心箭头从中心向外延伸。否则旋转时圆点会偏离实际定位位置看起来“跑偏”。另外一种就是修改锚点 但是这是邪修法不合适。我不会设计图随便找了一个icon所以现在也是’跑偏的’。3.2 修改init方法关闭系统定位init(controller:map.MapComponentController):void{this.mapControllercontroller;controller.setMapType(mapCommon.MapType.STANDARD);// 关闭系统定位图层controller.setMyLocationEnabled(false);controller.setMyLocationControlsEnabled(false);}3.3 传感器管理类SensorManager单例import{sensor}fromkit.SensorServiceKit;/** * 方位角回调函数类型 * param azimuth 设备方向角单位度范围 0~3600°正北顺时针增加 */exporttypeAngleCallback(azimuth:number)void;// 传感器管理类exportclassSensorManager{privatestaticinstance:SensorManager;privatecallback?:AngleCallback;// 用户注册的回调privateisListening:booleanfalse;// 是否正在监听staticgetInstance():SensorManager{if(!SensorManager.instance){SensorManager.instancenewSensorManager();}returnSensorManager.instance;}// 开始监听设备方向方位角start(callback:AngleCallback,interval:number100_000_000):void{if(this.isListening){console.warn(传感器已在监听中请先 stop());return;}// 检查设备是否支持方向传感器try{// 推荐直接获取指定类型的传感器列表constsensorssensor.getSensorListSync();if(sensors.length0){console.error(设备不支持方向传感器无法获取方位角);return;}}catch(error){console.error(获取方向传感器列表失败:${JSON.stringify(error)});return;}this.callbackcallback;// 订阅方向传感器try{sensor.on(sensor.SensorId.ORIENTATION,(data:sensor.OrientationResponse){constazimuthdata.alpha;// 0~360°this.callback?.(azimuth);},{interval:interval});}catch(error){console.error(订阅方向传感器失败:${JSON.stringify(error)});return;}this.isListeningtrue;console.info(开始监听设备方向间隔${interval}ns);}stop():void{if(!this.isListening)return;try{sensor.off(sensor.SensorId.ORIENTATION);}catch(error){console.error(停止传感器监听失败:${JSON.stringify(error)});}finally{this.isListeningfalse;this.callbackundefined;console.info(停止传感器监听);}}}四、地图箭头指向与现实手机指向相反箭头指向与手机实际朝向相反或偏差90°/180°的问题原因有二传感器alpha定义0° 北顺时针增加。但某些设备的传感器可能返回相反方向例如北为180°。图标自身方向如果图标设计为指向右侧90°则需减去90°。通用修正公式letcorrectedazimuth;// 情况1完全相反 → 加180°corrected(azimuth180)%360;// 情况2镜像翻转 → 取反corrected(360-azimuth)%360;// 情况3偏某个固定角度corrected(azimuthoffset360)%360;我们的是第一种情况完全相反调试建议用系统指南针 App 对比记录手机朝北时打印的azimuth值。若朝北打印 0无需修正若打印 180则加180°。若朝北打印其他值使用(360 - azimuth) % 360。我在实际测试中发现设备返回的alpha正好与地图旋转角相反因此采用(azimuth 180) % 360解决了问题。未修正方向修正后方向地图页监听传感器的方位角并且记录下来页面初始化开始监听页面结束释放定图更新除传递坐标增加方位角。以下代码只专注更新自定义箭头位置完整代码仓库下载。// Index.etsimport{SensorManager}from../common/managers/SensorManager;import{MapManager}from../common/managers/MapManager;import{geoLocationManager}fromkit.LocationKit;Entry Component struct Index{privatemapManager:MapManagernewMapManager();privatecurrentAzimuth:number0;aboutToAppear(){// 启动方向传感器SensorManager.getInstance().start((azimuth){// 反转方向加上 180 度再模 360 不然方向正好相反constcorrected(azimuth180)%360;this.currentAzimuthcorrected;this.mapManager.setMyLocationRotation(corrected);});}// 定位与轨迹处理方法 privateonLocationUpdate(rawLoc:geoLocationManager.Location){if(!rawLoc.latitude||!rawLoc.longitude)return;// 立即更新地图上的蓝点// this.mapController?.setMyLocation(rawLoc);// 坐标转换constgcjMapManager.convertWgs84ToGcj02(rawLoc.latitude,rawLoc.longitude);// 更新自定义圆点this.mapManager.updateMyLocationMarker(gcj.latitude,gcj.longitude,this.currentAzimuth);}privateasyncmoveToMyLocationIfNeeded(){if(this.hasMovedToMyLocation)return;if(!this.hasLocationPermission){console.warn(无定位权限跳过移动相机);return;}try{if(!geoLocationManager.isLocationEnabled()){this.showToast(请开启设备位置服务);return;}// 优先使用缓存位置constlastLocationgeoLocationManager.getLastLocation();if(lastLocationlastLocation.latitudelastLocation.longitude){constgcjMapManager.convertWgs84ToGcj02(lastLocation.latitude,lastLocation.longitude);// 更新自定义定位箭头位置 当前方向this.mapManager.updateMyLocationMarker(gcj.latitude,gcj.longitude,this.currentAzimuth);this.moveCameraToPoint(gcj.latitude,gcj.longitude,SportConstants.MAP_ZOOM_LEVEL);this.hasMovedToMyLocationtrue;console.info(使用缓存位置移动相机);}constrequest:geoLocationManager.SingleLocationRequest{locatingPriority:geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED,locatingTimeoutMs:SportConstants.SINGLE_LOCATION_TIMEOUT_MS};constlocationawaitgeoLocationManager.getCurrentLocation(request);this.mapController?.setMyLocation(location);constgcjMapManager.convertWgs84ToGcj02(location.latitude,location.longitude);this.moveCameraToPoint(gcj.latitude,gcj.longitude,SportConstants.MAP_ZOOM_LEVEL);this.hasMovedToMyLocationtrue;console.info(已移动到用户当前位置);}catch(error){console.error(定位失败,error);this.showToast(无法获取当前位置请点击开始运动后自动跟随,SportConstants.TOAST_DURATION_LONG);}}aboutToDisappear(){// 停止传感器释放资源SensorManager.getInstance().stop();this.mapManager.removeMyLocationMarker();this.stopTracking();}}五、完整流程图启动应用 ↓ 关闭系统定位图层 ↓ 创建自定义Marker箭头图标 ↓ 启动定位监听 → 更新Marker位置 ↓ 启动方向传感器 → 实时旋转Marker ↓ 用户转动手机 → 箭头同步旋转六、性能与功耗优化传感器间隔interval默认为 100ms100_000_000 ns既保证流畅又不过度耗电。可调整为game约20ms提升顺滑度。避免重复创建 Marker只在首次定位时创建后续复用。页面销毁时停止传感器在aboutToDisappear中调用SensorManager.stop()。七、总结通过关闭系统定位图层、自定义 Marker 并接入方向传感器我们实现了高精度、可自定义的定位箭头旋转效果。整个过程无需申请额外权限代码清晰性能优异。

相关文章:

鸿蒙运动健康实战:自定义定位箭头跟随手机方向旋转

告别系统蓝点,实现高精度自定义定位箭头,实时响应手机朝向,为运动轨迹应用增添使用交互体验。 完整源码:SportTrackDemo 在上一节中,我们已经实现了运动轨迹记录、后台长时任务申请等功能。但系统默认的“我的位置”蓝…...

MySQL入门实战:从零学写SQL,口语化生动讲解,新手也能轻松学会

MySQL从零开始完全教程|小白入门手把手教学生动口语化|7280字真实干货 嘿,朋友!别划走——你点开的不是那种“先讲ACID再扯CAP理论”的天书,也不是满屏SELECT * FROM sys.schema_table_statistics_with_buffer的炫技P…...

Multi-Agent 任务分解框架:从目标到子任务的可执行清单

Multi-Agent 任务分解框架:从目标到子任务的可执行清单 一、 引言 (Introduction) 1.1 钩子:当你拥有“一支 AI 团队”却不知道怎么派活? 假设你正在创业,或者在公司担任产品/技术负责人,现在需要完成一件综合性、跨专业、依赖协作反馈的任务——比如: 从零搭建一个面向…...

从0到1搭建Multi-Agent分析平台:LangGraph完整实战

从0到1搭建Multi-Agent分析平台:LangGraph完整实战 关键词:LangGraph、多智能体系统、Multi-Agent、LLM应用开发、状态管理、工具调用、可视化平台 摘要:本文将以**“像搭乐高积木一样组建AI分析团队”**为核心理念,从零开始一步步构建一个面向企业营销数据的Multi-Agent分…...

“神也不过如此” 央视采访张雪:17 年前张雪自问 3 个问题后果断辞职

4 月 13 日,「张雪问自己 3 个问题后辞职」冲上热搜,央视「面对面」栏目采访了这位国产机车领域的标志性人物。张雪凭借一段早年职业选择,再次引发全网职场人共鸣。①2009 年,22 岁的张雪已经在浙江金华某摩托车厂工作了 4 年&…...

【限时开源】我们刚交付的金融级AIAgent数据流引擎(支持动态拓扑+语义路由),含3大专利数据流编排协议

第一章:AIAgent架构数据流设计模式的范式演进 2026奇点智能技术大会(https://ml-summit.org) AI Agent 的数据流设计已从早期静态管道模型,逐步演进为具备动态感知、语义路由与闭环反馈能力的协同式范式。这一演进并非线性叠加,而是由底层基…...

【2026奇点大会独家解码】:AIAgent对话管理的5大认知拐点与企业落地避坑指南

第一章:【2026奇点大会独家解码】:AIAgent对话管理的5大认知拐点与企业落地避坑指南 2026奇点智能技术大会(https://ml-summit.org) 在2026奇点大会上,来自DeepMind、阿里通义实验室与MIT CSAIL的联合白皮书首次系统揭示:当前83…...

AIAgent不是微服务2.0:SITS2026圆桌用12组实测数据证伪主流架构方案,重构4层抽象模型

第一章:SITS2026圆桌:AIAgent架构的未来方向 2026奇点智能技术大会(https://ml-summit.org) 在SITS2026圆桌讨论中,来自DeepMind、Anthropic、阿里通义实验室及MIT CSAIL的七位架构师一致指出:AIAgent正从“单体推理引擎”向“分…...

【AIAgent架构核心机密】:基于237个真实项目验证的目标分解熵值模型(附可运行评估脚本)

第一章:目标分解在AIAgent架构中的战略定位 2026奇点智能技术大会(https://ml-summit.org) 目标分解并非AI Agent开发中的辅助技巧,而是其认知架构的底层编排范式。它将高层任务语义(如“策划一场低碳主题的社区科普活动”)系统性…...

AFPN渐进式特征金字塔网络:解决非相邻层级特征融合的突破性方案

1. 为什么我们需要AFPN? 在计算机视觉领域,目标检测一直是个热门话题。想象一下,你要在一张照片里找出所有的猫——这听起来简单,但要让计算机做到这一点可不容易。传统的方法就像让一个近视的人在不同距离观察物体:离…...

告别pip install tensorrt:手把手教你用TensorRT 10.0的tar包在Ubuntu 22.04上搭建稳定AI推理环境

告别pip install tensorrt:手把手教你用TensorRT 10.0的tar包在Ubuntu 22.04上搭建稳定AI推理环境 在AI模型部署领域,TensorRT作为NVIDIA推出的高性能推理引擎,能够显著提升模型在NVIDIA GPU上的运行效率。然而,许多开发者习惯性地…...

【词汇专栏】扩散模型(Diffusion Model):AI 是怎么“画“出一张图的?

扩散模型(Diffusion Model):AI 是怎么"画"出一张图的?你输入一句话,AI 生成了一张精美的图片。这背后不是什么神奇魔法,而是一个极其优雅的数学过程——先把图片"毁掉",再学…...

【词汇专栏】AGI vs ANI vs ASI:人工智能的三种“等级“,我们现在在哪里?

AGI vs ANI vs ASI:人工智能的三种"等级",我们现在在哪里? 马斯克说 AGI 即将到来。OpenAI 说他们的使命是安全地构建 AGI。科学家们警告 ASI 可能危及人类。这三个缩写词到底是什么意思?我们现在处于哪个阶段&#xff…...

【词汇专栏】MoE(混合专家):为什么 DeepSeek 又快又省钱?

MoE(混合专家):为什么 DeepSeek 又快又省钱? DeepSeek-V3 有 6710 亿个参数,但运行速度比 GPT-4o 还快?Gemini 1.5 Pro 能处理 100 万词元(Token)还不崩溃?这背后的秘密&…...

Z-Image-Turbo-rinaiqiao-huiyewunv多场景落地:AI绘画教育课程实验平台搭建实践

Z-Image-Turbo-rinaiqiao-huiyewunv多场景落地:AI绘画教育课程实验平台搭建实践 1. 项目背景与核心价值 在教育数字化转型的浪潮中,AI绘画技术正成为艺术教育创新的重要驱动力。Z-Image Turbo (辉夜大小姐-日奈娇)作为一款专为二次元人物绘图优化的工具…...

初学者必看!如何解决Java线程不安全问题

对于java初学者来说,应该听过Java线程不安全的问题:线程修改变量时,会将变量拷贝到本地内存,修改完成后,再写回主内存。这个过程中,如果多个线程同时访问并修改同一个数据,就会出现线程安全问题…...

Wan2.2-I2V-A14B文生视频实战:教育课件动态演示视频批量生成案例

Wan2.2-I2V-A14B文生视频实战:教育课件动态演示视频批量生成案例 1. 教育视频制作的痛点与解决方案 传统教育课件视频制作面临三大难题:一是专业制作成本高,需要聘请视频团队;二是内容更新迭代慢,无法快速响应教学需…...

别再死磕Ubuntu16.04了!Zephyr RTOS环境搭建保姆级避坑指南(附nRF52840DK实战)

别再死磕Ubuntu16.04了!Zephyr RTOS环境搭建保姆级避坑指南(附nRF52840DK实战) 如果你正在尝试搭建Zephyr RTOS开发环境,却频繁遭遇各种诡异错误,很可能是因为你还在使用Ubuntu 16.04这样的老旧系统版本。作为一款面向…...

Qwen3-4B镜像快速入门:免Python免CUDA,浏览器打开就能聊

Qwen3-4B镜像快速入门:免Python免CUDA,浏览器打开就能聊 1. 为什么选择这个镜像? 想象一下:你刚拿到一台新电脑,想体验最新的大语言模型,但发现需要先安装Python、配置CUDA、解决各种依赖冲突...这个过程…...

薪酬系统上线踩坑实录:从Excel算薪到自动化发薪,我们走了多少弯路

薪酬系统是帮助企业实现薪资核算、社保公积金计算、个税申报和薪资发放全流程自动化的管理工具。 一套成熟的薪酬系统能将每月算薪时间从5-7个工作日压缩到1-2天,同时将核算差错率控制在0.1%以下。对于200人以上的企业来说,手工算薪的隐性成本远比想象中…...

LM2904运算放大器的实战应用:精准监测电池电压的电路设计

1. LM2904运算放大器:电池监测的"火眼金睛" 第一次接触电池电压监测时,我拿着万用表手动测量的狼狈场景至今难忘。直到发现LM2904这颗神器,才真正体会到什么叫"科技改变工作方式"。这款双运放芯片就像给电路装上了24小时…...

2026年企业薪酬管理的数字化底座:eHR工资系统

eHR工资系统是企业人力资源管理系统(eHR)中负责薪酬核算、发放与管理的核心模块,它将传统手工算薪转变为自动化、规则化的数字流程。 一套成熟的eHR工资系统能覆盖薪资结构配置、个税计算、社保公积金联动、多维度薪酬报表等场景&#xff0c…...

Linux环境下Nacos 2.4.0安全部署与密码重置实战指南

1. 环境准备与基础配置 在Linux系统上部署Nacos 2.4.0之前,需要先确保基础环境就绪。我最近在阿里云ECS上部署时发现,很多安全问题都源于环境配置不当。这里分享几个关键检查点: 首先用java -version确认JDK版本。实测发现JDK17比JDK8性能提…...

智能考勤管理系统推荐:2026年主流产品深度对比与选型建议

智能考勤管理系统是帮助企业实现员工出勤数据自动采集、工时智能计算、排班自动优化的数字化管理工具。 2026年主流的智能考勤系统已普遍集成AI能力,支持多终端打卡(GPS、WiFi、人脸识别、蓝牙)、复杂排班规则自动生成、异常考勤智能预警&am…...

Windows远程连接Ubuntu 22.04桌面终极指南:解决xrdp卡顿、分辨率异常和QtGUI问题

Windows远程连接Ubuntu 22.04桌面终极指南:解决xrdp卡顿、分辨率异常和QtGUI问题 远程桌面连接是开发者跨平台工作的常见需求。当Windows用户需要访问Ubuntu 22.04桌面环境时,xrdp服务提供了一个轻量级的解决方案。然而在实际使用中,用户常会…...

监管倒计时60天:AIAgent可解释性设计必须满足的5项ISO/IEC 23894-2023强制条款

第一章:AIAgent可解释性设计的合规性基线与监管紧迫性 2026奇点智能技术大会(https://ml-summit.org) 随着欧盟《人工智能法案》(AI Act)全面生效、美国NIST AI RMF 1.1强制纳入联邦采购流程,以及中国《生成式人工智能服务管理暂…...

XHS-Downloader:3种高效方法帮你轻松下载小红书无水印内容

XHS-Downloader:3种高效方法帮你轻松下载小红书无水印内容 【免费下载链接】XHS-Downloader 小红书(XiaoHongShu、RedNote)链接提取/作品采集工具:提取账号发布、收藏、点赞、专辑作品链接;提取搜索结果作品、用户链接…...

WPF 多屏显示实战:从零构建跨屏窗口管理器,避坑指南与性能优化

1. WPF多屏显示的核心挑战与解决方案 在工业控制、数字看板等场景中,多屏显示是刚需。但很多开发者第一次尝试时都会遇到这样的问题:明明代码逻辑正确,窗口却始终在主屏幕弹出,或者在不同DPI的屏幕上出现显示错位。这背后涉及三个…...

py每日spider案例之下载gou 之视频解析接口(难度一般)

逆向代码: crypto=require(crypto) async function confidential(params) {const salt = "bf5941f27ee14d9ba9ebb72d89de5dea";const</...

从零搭建到安全加固:CMAK for Apache Kafka 生产环境部署全记录(含LDAP配置避坑)

从零构建金融级Kafka监控体系&#xff1a;CMAK生产部署与LDAP深度集成实战 金融科技场景下的Kafka集群管理&#xff0c;从来都不只是技术参数的简单堆砌。当某跨国支付平台因监控盲区导致消息积压事故时&#xff0c;他们最终选择了CMAK作为监控解决方案——这个源自Yahoo开源的…...