前言
在开发运动类应用时,集成地图功能以及实时记录运动轨迹和公里数是核心需求之一。本文将详细介绍如何在 HarmonyOS 应用中集成百度地图 SDK,实现运动跟随以及运动公里数的记录。
一、集成百度地图 SDK
1.引入依赖
首先,需要在项目的文件中引入百度地图相关的依赖包:- "dependencies": {
- "@bdmap/base": "1.2.6",
- "@bdmap/search": "1.2.6",
- "@bdmap/map": "1.2.6",
- "@bdmap/locsdk": "1.1.4"
- }
复制代码 2.初始化百度地图
为了使用百度地图的功能,我们需要进行初始化操作。这包括设置 API Key 和初始化定位客户端。
MapUtil 类- export class MapUtil{
- public static initialize(context:Context){
- Initializer.getInstance().initialize("你的key");
- // 设置是否同意隐私合规政策接口
- // true,表示同意隐私合规政策
- // false,表示不同意隐私合规政策
- LocationClient.checkAuthKey("你的key", (result: string) => {
- console.debug("result = " + result); // 可打印出是否鉴权成功的结果
- });
- LocationClient.setAgreePrivacy(true);
- LocManager.getInstance().init(context);
- }
- }
复制代码 LocManager 类- export class LocManager {
- private client: LocationClient | null = null;
- private static instance: LocManager;
- public static getInstance(): LocManager {
- if (!LocManager.instance) {
- LocManager.instance = new LocManager();
- }
- return LocManager.instance;
- }
- constructor() {
- }
- init(context: Context) {
- if (this.client == null) {
- try {
- this.client = new LocationClient(context);
- } catch (error) {
- console.error("harmony_baidu_location error: " + error.message);
- }
- }
- if (this.client != null) {
- this.client.setLocOption(this.getDefaultLocationOption());
- }
- }
- start() {
- if (this.client != null) {
- this.client.start();
- }
- }
- stop() {
- if (this.client != null) {
- this.client.stop();
- }
- }
- requestSingleLocation() {
- if (this.client != null) {
- this.client.requestSingleLocation();
- }
- }
- registerListener(listener: BDLocationListener): boolean {
- let isSuccess: boolean = false;
- if (this.client != null && listener != null) {
- this.client.registerLocationListener(listener);
- isSuccess = true;
- }
- return isSuccess;
- }
- unRegisterListener(listener: BDLocationListener) {
- if (this.client != null && listener != null) {
- this.client.unRegisterLocationListener(listener);
- }
- }
- getSDKVersion(): string {
- let version: string = "";
- if (this.client != null) {
- version = this.client.getVersion();
- }
- return version;
- }
- enableLocInBackground(wantAgent: WantAgent) {
- if (this.client != null) {
- this.client.enableLocInBackground(wantAgent);
- }
- }
- disableLocInBackground() {
- if (this.client != null) {
- this.client.disableLocInBackground();
- }
- }
- getDefaultLocationOption() {
- let option = new LocationClientOption();
- option.setCoorType("bd09ll"); // 可选,默认为gcj02,设置返回的定位结果坐标系
- option.setTimeInterval(3); // 可选,默认1秒,设置连续定位请求的时间间隔
- option.setDistanceInterval(0); // 可选,默认0米,设置连续定位的距离间隔
- option.setIsNeedAddress(true); // 可选,设置是否需要地址信息,默认不需要
- option.setIsNeedLocationDescribe(true); // 可选,默认为false,设置是否需要地址描述
- option.setIsNeedLocationPoiList(true); // 可选,默认能为false,设置是否需要POI结果
- option.setLocationMode(LocationMode.High_Accuracy); // 可选,默认高精度,设置定位模式,高精度、低功耗、仅设备
- option.setSingleLocatingTimeout(3000); // 可选,仅针对单次定位生效,设置单次定位的超时时间
- return option;
- }
- }
复制代码 3.定位监听器
为了处理定位数据,我们需要实现一个定位监听器:- export class MapLocationListener extends BDLocationListener {
- private callback: (location: BDLocation) => void;
- constructor(callback: (location: BDLocation) => void) {
- super();
- this.callback = callback;
- }
- onReceiveLocation(bdLocation: BDLocation): void {
- this.callback(bdLocation);
- }
- }
复制代码 二、页面使用
1.权限申请
在文件中声明所需的权限:- "requestPermissions": [
- {
- "name": "ohos.permission.LOCATION",
- "reason": "$string:location_permission",
- "usedScene": {
- "abilities": [
- "EntryAbility"
- ],
- "when": "inuse"
- }
- },
- {
- "name": "ohos.permission.LOCATION_IN_BACKGROUND",
- "reason": "$string:background_location_permission",
- "usedScene": {
- "abilities": [
- "EntryAbility"
- ],
- "when": "inuse"
- }
- },
- {
- "name": "ohos.permission.APPROXIMATELY_LOCATION",
- "reason": "$string:fuzzy_location_permission",
- "usedScene": {
- "abilities": [
- "EntryAbility"
- ],
- "when": "inuse"
- }
- },
- {
- "name": "ohos.permission.APP_TRACKING_CONSENT",
- "reason": "$string:get_oaid_permission",
- "usedScene": {
- "abilities": [
- "EntryAbility"
- ],
- "when": "inuse"
- }
- },
- {
- "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
- "reason": "$string:keep_background_running_permission",
- "usedScene": {
- "abilities": [
- "EntryAbility1"
- ],
- "when": "inuse"
- }
- }
- ]
复制代码 2.请求权限
在页面中请求权限:- private async requestPermissions(): Promise<boolean> {
- const permissions : Permissions[]= [
- 'ohos.permission.LOCATION',
- 'ohos.permission.APPROXIMATELY_LOCATION',
- 'ohos.permission.APP_TRACKING_CONSENT',
- ]
- return LibPermission.requestPermissions(permissions)
- }
复制代码 3.页面调用
方向感应
使用鸿蒙系统自带的方向传感器来获取设备的朝向角度:- // 初始化方向传感器
- sensor.on(sensor.SensorId.ORIENTATION, (data) => {
- // 获取设备朝向角度(绕Z轴旋转角度)
- this.currentRotation = data.alpha;
- if(this.loc){
- this.loc.location = new LatLng(this.currentLatitude, this.currentLongitude);
- this.loc.direction = this.currentRotation;
- this.loc.radius = 0;
- }
- });
- // 用完记得取消监听
- sensor.off(sensor.SensorId.ORIENTATION);
复制代码 编写定位监听器- private mListener: MapLocationListener = new MapLocationListener((bdLocation: BDLocation) => {
- this.currentLatitude = bdLocation.getLatitude();
- this.currentLongitude = bdLocation.getLongitude();
- this.currentRadius = bdLocation.getRadius();
- // 更新地图位置和位置标记
- if (this.mapController) {
- // 更新地图中心点
- this.mapController.setMapCenter({
- lat: this.currentLatitude,
- lng: this.currentLongitude
- },15);
- if(this.loc){
- // 设置定位图标位置、指向以及范围
- this.loc.location = new LatLng(this.currentLatitude, this.currentLongitude);
- this.loc.direction = this.currentRotation;
- // 单位米
- this.loc.radius = 0;
- }
- }
- });
复制代码 启动和关闭定位- // 启动定位
- LocManager.getInstance().registerListener(this.mListener);
- LocManager.getInstance().start();
- // 关闭定位
- LocManager.getInstance().unRegisterListener(this.mListener);
- LocManager.getInstance().stop();
复制代码 百度地图集成
在页面中集成百度地图:- MapComponent({ onReady: async (err, mapController:MapController) => {
- if (!err) {
- // 获取地图的控制器类,用来操作地图
- this.mapController= mapController;
- let result = this.mapController.getLayerByTag(SysEnum.LayerTag.LOCATION);
- if(result){
- this.loc = result as LocationLayer;
- }
- if(this.currentLatitude!=0&&this.currentLongitude!=0){
- if(this.loc){
- // 设置定位图标位置、指向以及范围
- this.loc.location = new LatLng(this.currentLatitude, this.currentLongitude);
- this.loc.direction = this.currentRotation;
- // 单位米
- this.loc.radius = 0;
- }
- this.mapController.setMapCenter({
- lat: this.currentLatitude,
- lng: this.currentLongitude
- },15);
- }
- }
- }, mapOptions: this.mapOpt }).width('100%').height('100%')
复制代码 三、公里数计算
在运动应用中,记录用户的运动轨迹并计算运动的总距离是核心功能之一。为了实现这一功能,我们需要设计一个数据模型来记录运动轨迹点,并通过这些点计算总距离。
1.运动轨迹点模型
定义一个RunPoint类来表示运动轨迹中的一个点,包含纬度、经度和时间戳:- /**
- * 运动轨迹点数据模型
- */
- export class RunPoint {
- // 纬度
- latitude: number;
- // 经度
- longitude: number;
- // 时间戳
- timestamp: number;
- // 所属公里数分组(第几公里)
- kilometerGroup: number;
- constructor(latitude: number, longitude: number) {
- this.latitude = latitude;
- this.longitude = longitude;
- this.timestamp = Date.now();
- this.kilometerGroup = 0; // 默认分组为0
- }
- }
复制代码 2.运动轨迹管理类
创建一个RunTracker类来管理运动轨迹点,并计算总距离:- /**
- * 运动轨迹管理类
- */
- export class RunTracker {
- // 所有轨迹点
- private points: RunPoint[] = [];
- // 当前总距离(公里)
- private totalDistance: number = 0;
- // 当前公里数分组
- private currentKilometerGroup: number = 0;
- /**
- * 添加新的轨迹点
- * @param latitude 纬度
- * @param longitude 经度
- * @returns 当前总距离(公里)
- */
- addPoint(latitude: number, longitude: number): number {
- const point = new RunPoint(latitude, longitude);
- if (this.points.length > 0) {
- // 计算与上一个点的距离
- const lastPoint = this.points[this.points.length - 1];
- const distance = this.calculateDistance(lastPoint, point);
- this.totalDistance += distance;
- // 更新公里数分组
- point.kilometerGroup = Math.floor(this.totalDistance);
- if (point.kilometerGroup > this.currentKilometerGroup) {
- this.currentKilometerGroup = point.kilometerGroup;
- }
- }
- this.points.push(point);
- return this.totalDistance;
- }
- /**
- * 计算两点之间的距离(公里)
- * 使用Haversine公式计算球面距离
- */
- private calculateDistance(point1: RunPoint, point2: RunPoint): number {
- const R = 6371; // 地球半径(公里)
- const lat1 = this.toRadians(point1.latitude);
- const lat2 = this.toRadians(point2.latitude);
- const deltaLat = this.toRadians(point2.latitude - point1.latitude);
- const deltaLon = this.toRadians(point2.longitude - point1.longitude);
- const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
- Math.cos(lat1) * Math.cos(lat2) *
- Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
- return R * c;
- }
- /**
- * 将角度转换为弧度
- */
- private toRadians(degrees: number): number {
- return degrees * (Math.PI / 180);
- }
- /**
- * 获取当前总距离
- */
- getTotalDistance(): number {
- return this.totalDistance;
- }
- /**
- * 获取指定公里数分组的轨迹点
- */
- getPointsByKilometer(kilometer: number): RunPoint[] {
- return this.points.filter(point => point.kilometerGroup === kilometer);
- }
- /**
- * 清空轨迹数据
- */
- clear(): void {
- this.points = [];
- this.totalDistance = 0;
- this.currentKilometerGroup = 0;
- }
- }
复制代码 3.页面的监听器里记录公里数
在页面中使用RunTracker类来记录运动轨迹点并计算总距离:- private runTracker: RunTracker = new RunTracker();
- 监听器添加代码
- const distance = this.runTracker.addPoint(this.currentLatitude, this.currentLongitude);
- distance就是当前运动的公里数
复制代码 四、总结
本文详细介绍了如何在 HarmonyOS 应用中集成百度地图 SDK,实现运动跟随以及运动公里数的记录。通过以下步骤,我们可以实现一个功能完整的运动应用:
• 集成百度地图 SDK:
• 引入必要的依赖包。
• 初始化百度地图并设置定位选项。
• 页面使用:
• 请求必要的权限。
• 启动和关闭定位。
• 实时更新地图位置和方向。
• 公里数计算:
• 定义运动轨迹点模型。
• 使用 Haversine 公式计算两点之间的距离。
• 记录运动轨迹点并实时更新总距离。
通过这些步骤,开发者可以轻松实现一个功能强大的运动应用,为用户提供实时的运动数据和地图跟随功能。希望本文的内容能够帮助你在 HarmonyOS 开发中取得更好的成果!
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |