更新记录

1.0.8(2026-08-11)

增加地理围栏功能

1.0.7(2026-07-19)

去掉无用资源

1.0.6(2026-07-19)

修复安卓端步行导航没有声音的问题

查看更多

平台兼容性

uni-app(5.07)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - 5.0 12 ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(5.07)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - - -

pow-bmapx 百度地图SDK插件

插件选型

地图厂商 插件 uni-app uni-app x 鸿蒙 插件市场
百度 pow-bmapx 支持 支持 不支持 查看插件
高德 pow-amapall 支持 支持 不支持 查看插件
高德 pow-amapx 不支持 支持 支持 查看插件
腾讯 pow-tencentmap 支持 支持 不支持 查看插件
腾讯 pow-tmapx 不支持 支持 支持 查看插件
谷歌 pow-googlemap 支持 支持 不支持 查看插件

版本说明

  • 老版本项目在接入、升级或新增功能前,请先确认当前工程使用的是哪一套原生 SDK,再选择对应的插件版本。
  • 如果现有功能还不够,或者需要新增能力,可以在插件市场页面点击 进入交流群 联系沟通。
  • 只要原生 SDK 已经提供对应能力,插件内都可以继续支持和扩展实现。

开发文档

功能概述

百度地图定位、搜索、导航全功能插件,支持uniapp 和 uni-app x 项目,支持安卓 和 ios

主要功能

  • 支持单次定位和持续定位
  • 支持POI搜索(关键词搜索、周边搜索、多关键词并集搜索)
  • 支持地理编码和逆地理编码
  • 支持路线规划(驾车、步行、骑行)
  • 支持驾车导航、货车导航(GPS导航/模拟导航)
  • 支持步行导航、骑行导航、步行 AR 导航
  • 支持坐标转换(GPS/GCJ02转百度坐标)
  • 支持距离计算和面积计算
  • 支持TTS语音播报(多语言)
  • 支持地图组件(折线、圆形、多边形、Marker等)
  • 支持百度鹰眼服务端圆形/多边形围栏及进出围栏实时告警(Android/iOS)

使用步骤

  1. 申请百度地图Key(Android Key、iOS Key) 插件内导航播报和普通 TTS 均走系统语音,无需再额外申请百度 TTS 参数
  2. 导入本插件到自己项目
  3. 把 demo 中的 pages/index/index.uvue 内的initSDK1方法,复制到自己项目的 App.vueonLaunch 方法内。
  4. 把插件内的 uni_modules/pow-bmapx/utssdk/app-android/AndroidManifest.xml 内的 com.baidu.lbsapi.API_KEY的值改成自己的百度 key
  5. 打自定义基座
  6. 调用定位、导航、地图等相关方法

使用鹰眼围栏时,还需要在百度鹰眼控制台创建服务并准备 serviceIdentityName。Android 鹰眼 SDK 必须使用与当前包名、SHA1 匹配的 Android 类型 AK;iOS 必须使用 iOS 类型 AK,插件内部固定使用当前 App 的 bundleId 作为 mcode,JS 无需传入。服务端类型 AK 仅用于后端调用鹰眼 Web Service API,不能用于启动端侧 SDK。新增原生依赖后必须重新制作自定义基座。

Android 鹰眼 3.2.2 使用 JitPack 远程依赖 com.github.a83988029:mybaidutrace:v3.2.2-nodup.2,仅支持 arm64-v8aarmeabi-v7a 真机架构。请勿改回 com.baidu.lbs:trace:3.2.2,该官方 Maven 包会与百度地图 SDK 的 com.baidu.lbsyun:common 产生重复类冲突。


iOS 包大小超限解决方案

由于插件内的资源包较大,打包时可以选择以下任一方案:

方案一:直接打包

打包前保留插件内的 iOS 资源包并直接打包。制作自定义基座时会因包大小超限,需要支付 5 元。

  • 优点:操作方便。
  • 缺点:需要支付 5 元的包大小超限费用。

方案二:打包后放回资源包

  1. 打包前删除插件内 iOS 资源包的 resources 目录。
  2. 完成打包后,按照视频教程中的方法,将资源包放回安装包内。
  • 优点:打包不会超限,无需支付 5 元。
  • 缺点:操作稍微麻烦一些。

API 文档

1. SDK初始化

import { initBmapSDK } from '@/uni_modules/pow-bmapx'

// Android / iOS
initBmapSDK('your_baidu_key')

2. 定位权限

import { checkAndRequestLocationPermission } from '@/uni_modules/pow-bmapx'

// 检查并请求定位权限
checkAndRequestLocationPermission((res: UTSJSONObject) => {
    const errCode = res['errCode']
    const msg = res['msg']
    if (errCode == 0) {
        console.log('定位权限已授予')
    } else {
        console.log(`权限请求失败: ${msg}`)
    }
})

3. 单次定位

import { getBmapLocation } from '@/uni_modules/pow-bmapx'

getBmapLocation({
    needAddress: true  // 是否需要返回地址信息
}, (res: UTSJSONObject) => {
    const errCode = res['errCode']
    if (errCode == 0) {
        const lat = res['lat']      // 纬度
        const lon = res['lon']      // 经度
        const address = res['address']  // 地址
        const city = res['city']        // 城市
        const district = res['district'] // 区县
        console.log(`定位成功: ${lat}, ${lon}, ${address}`)
    } else {
        console.log(`定位失败: ${res['msg']}`)
    }
})

4. 持续定位

import { startBmapLocation, stopBmapLocation } from '@/uni_modules/pow-bmapx'

// 开始持续定位
startBmapLocation({
    interval: 3000,     // 定位间隔,单位毫秒
    needAddress: true   // 是否需要地址信息
}, (res: UTSJSONObject) => {
    const errCode = res['errCode']
    if (errCode == 0) {
        const lat = res['lat']
        const lon = res['lon']
        console.log(`持续定位: ${lat}, ${lon}`)
    }
})

// 停止持续定位
stopBmapLocation()

5. POI搜索

import { searchBmapPois } from '@/uni_modules/pow-bmapx'

// 关键词搜索
searchBmapPois({
    keywords: ['餐厅'],      // 搜索关键词
    lat: 39.91054,           // 中心点纬度
    lon: 116.398111,         // 中心点经度
    radius: 5000,            // 搜索半径(米)
    city: '北京',            // 城市(可选)
    pageSize: 20             // 每页数量
}, (res: UTSJSONObject) => {
    const errCode = res['errCode']
    if (errCode == 0) {
        const pois = res['pois'] as Array<UTSJSONObject>
        pois.forEach(poi => {
            console.log(`${poi['name']} - ${poi['address']}`)
        })
    }
})

// 多关键词并集搜索(关键词用$分隔)
searchBmapPois({
    keywords: ['餐厅', '酒店', '购物'],  // 多个关键词
    lat: 39.91054,
    lon: 116.398111,
    radius: 2000,
    pageSize: 20
}, callback)

// 周边搜索(不传关键词则使用默认关键词)
searchBmapPois({
    keywords: [''],  // 空关键词会使用默认搜索词
    lat: 39.91054,
    lon: 116.398111,
    radius: 2000,
    pageSize: 20
}, callback)

6. 地理编码

import { searchBmapGeocode, searchBmapRegeocode } from '@/uni_modules/pow-bmapx'

// 地理编码(地址转坐标)
searchBmapGeocode('天安门', '北京', (res: UTSJSONObject) => {
    const errCode = res['errCode']
    if (errCode == 0) {
        const addressList = res['addressList'] as Array<UTSJSONObject>
        if (addressList.length > 0) {
            const addr = addressList[0]
            console.log(`坐标: ${addr['lat']}, ${addr['lon']}`)
        }
    }
})

// 逆地理编码(坐标转地址)
searchBmapRegeocode(39.91054, 116.398111, (res: UTSJSONObject) => {
    const errCode = res['errCode']
    if (errCode == 0) {
        const address = res['address']
        const city = res['city']
        const district = res['district']
        console.log(`地址: ${address}`)
    }
})

7. 路线规划

import {
    searchBmapDriveRoute,
    searchBmapWalkRoute,
    searchBmapRideRoute
} from '@/uni_modules/pow-bmapx'

// 驾车路线规划
// strategy: 0-时间优先, 1-躲避拥堵, 2-最短距离, 3-较少费用
searchBmapDriveRoute(
    39.9028, 116.4271,    // 起点:北京站
    40.0486, 116.6095,    // 终点:首都机场T3
    0,                     // 策略:时间优先
    (res: UTSJSONObject) => {
        const errCode = res['errCode']
        if (errCode == 0) {
            const distance = res['distance'] as Number  // 距离(米)
            const duration = res['duration'] as Number  // 时长(秒)
            const polyline = res['polyline']  // 路线坐标点
            const steps = res['steps']        // 导航步骤
            console.log(`距离: ${(distance / 1000).toFixed(1)}公里`)
            console.log(`时长: ${Math.floor(duration / 60)}分钟`)
        }
    }
)

// 步行路线规划
searchBmapWalkRoute(
    39.9028, 116.4271,    // 起点
    40.0486, 116.6095,    // 终点
    (res: UTSJSONObject) => {
        // 同上
    }
)

// 骑行路线规划
searchBmapRideRoute(
    39.9028, 116.4271,    // 起点
    40.0486, 116.6095,    // 终点
    (res: UTSJSONObject) => {
        // 同上
    }
)

8. 导航功能

import {
    initBmapNaviSDK,
    isBmapNaviInitialized,
    prepareNaviPermissions,
    startBmapNavi,
    startBmapGPSNavi,
    startBmapSimulateNavi,
    stopBmapNavi
} from '@/uni_modules/pow-bmapx'

// 1. 准备导航权限
prepareNaviPermissions((res: UTSJSONObject) => {
    if (res['errCode'] != 0) {
        console.log('权限获取失败')
        return
    }

    // 2. 初始化导航SDK
    if (!isBmapNaviInitialized()) {
        initBmapNaviSDK((initRes: UTSJSONObject) => {
            if (initRes['errCode'] == 0) {
                console.log('导航SDK初始化成功')
                startNavigation()
            }
        })
    } else {
        startNavigation()
    }
})

// 3. 开始导航
function startNavigation() {
    const naviOptions: UTSJSONObject = {
        start: {
            lat: 39.909187,
            lon: 116.397455,
            name: '北京站'
        },
        end: {
            lat: 39.917839,
            lon: 116.397029,
            name: '故宫博物院'
        },
        // 途经点(可选,最多3个)
        via: [{
            lat: 39.913,
            lon: 116.400,
            name: '途经点1'
        }],
        naviType: 'drive',      // 导航类型: drive-驾车, truck-货车, walk-步行, walk-ar-步行AR, ride-骑行
        preference: 'time_first', // 路线偏好: time_first-时间优先, no_toll-不走收费, avoid_jam-躲避拥堵, no_highway-不走高速, highway_first-高速优先
        simulate: false          // 是否模拟导航
    }

    startBmapNavi(naviOptions, (res: UTSJSONObject) => {
        const type = res['type'] as string
        const info = res['info'] as UTSJSONObject

        switch (type) {
            case 'routePlanStart':
                console.log('开始规划路线')
                break
            case 'routePlanSuccess':
                console.log('路线规划成功')
                // 驾车/货车导航:需要再调用 GPS/模拟导航
                if (naviOptions['naviType'] == 'drive' || naviOptions['naviType'] == 'truck') {
                    startBmapGPSNavi()      // GPS导航
                    // startBmapSimulateNavi() // 模拟导航
                }
                // 步行/骑行/步行AR:插件会在算路成功后直接拉起导航页面
                break
            case 'routePlanFailed':
                console.log('路线规划失败')
                break
            case 'startNavi':
                console.log('导航开始')
                break
            case 'naviTTS':
                // 导航SDK回调的播报文案,插件内部会统一走 speakText 播放
                console.log('导航播报:', info['text'])
                break
            case 'naviInfo':
                // 导航信息更新
                const remainDistance = info['remainDistance']
                const remainTime = info['remainTime']
                break
            case 'arriveDestination':
                console.log('到达目的地')
                break
            case 'endNavi':
                console.log('导航结束')
                break
        }
    })
}

// 停止导航
stopBmapNavi()

// 步行导航示例
startBmapNavi({
    start: { lat: 39.909187, lon: 116.397455, name: '北京站' },
    end: { lat: 39.917839, lon: 116.397029, name: '故宫博物院' },
    naviType: 'walk'
}, (res: UTSJSONObject) => {})

// 步行AR导航示例
startBmapNavi({
    start: { lat: 39.909187, lon: 116.397455, name: '北京站' },
    end: { lat: 39.917839, lon: 116.397029, name: '故宫博物院' },
    naviType: 'walk-ar'
}, (res: UTSJSONObject) => {})

// 骑行导航示例
startBmapNavi({
    start: { lat: 39.909187, lon: 116.397455, name: '北京站' },
    end: { lat: 39.917839, lon: 116.397029, name: '故宫博物院' },
    naviType: 'ride'
}, (res: UTSJSONObject) => {})

9. 工具功能

import {
    bmapCoordFromOtherCoord,
    bmapLineDistance,
    bmapCalculateArea
} from '@/uni_modules/pow-bmapx'

// 坐标转换(其他坐标系转百度坐标)
// from: 'gps'/'wgs84' 或 'gcj02'/'google'/'amap'
const result = bmapCoordFromOtherCoord('gps', 39.9087, 116.3975)
const bdLat = result['lat']
const bdLon = result['lon']

// 计算两点直线距离(米)
const distance = bmapLineDistance(39.91054, 116.398111, 39.9087, 116.3975)
console.log(`直线距离: ${distance.toFixed(2)}米`)

// 计算矩形区域面积(平方米)
const area = bmapCalculateArea(39.92, 116.38, 39.90, 116.42)
console.log(`面积: ${area.toFixed(2)}平方米`)

10. TTS语音播报

import { speakText, stopSpeak, shutdownTTS } from '@/uni_modules/pow-bmapx'

// 播放语音
// language: 'zh'-中文, 'en'-英语, 'ru'-俄语
// speed: 语速 0.1-2.0
speakText('前方500米右转', 'zh', 0.55)

// 停止播放
stopSpeak()

// 释放TTS资源(退出时调用)
shutdownTTS()

地图组件

基本用法

<template>
    <view class="container">
        <pow-bmapx
            ref="mapRef"
            class="map"
            :center="mapCenter"
            :zoomLevel="mapZoomLevel"
            @load="onMapLoad"
            @mapLoaded="onMapLoaded"
            @markerClick="onMarkerClick"
            @markerDrag="onMarkerDrag"
            @cameraChange="onCameraChange"
        ></pow-bmapx>
    </view>
</template>

<script>
export default {
    data() {
        return {
            mapCenter: '116.398111,39.91054',  // 经度,纬度
            mapZoomLevel: 12
        }
    },
    methods: {
        onMapLoad() {
            console.log('地图加载完成')
        },
        onMapLoaded(e) {
            console.log('地图已加载')
        },
        onMarkerClick(e) {
            console.log('Marker点击:', e.detail)
        },
        onMarkerDrag(e) {
            console.log('Marker拖拽:', e.detail)
        },
        onCameraChange(e) {
            console.log('视角变化:', e.detail)
        }
    }
}
</script>

<style>
.map {
    width: 100%;
    height: 500rpx;
}
</style>

地图控制方法

const mapRef = this.$refs['mapRef'] as PowBmapxElement

// 设置地图类型 (1=普通, 2=卫星, 3=空白)
mapRef.setMapType(1)

// 显示/隐藏实时路况
mapRef.showTraffic(true)

// 显示自身位置
mapRef.showMyLocation(JSON.stringify({
    show: true,
    mode: 'normal'  // 'normal'-普通, 'following'-跟随, 'compass'-罗盘
}))

// 手势控制
mapRef.setZoomGesturesEnabled(true)    // 缩放手势
mapRef.setScrollGesturesEnabled(true)  // 拖拽手势
mapRef.setRotateGesturesEnabled(true)  // 旋转手势
mapRef.setTiltGesturesEnabled(true)    // 倾斜手势

// UI控件
mapRef.setCompassEnabled(true)         // 指南针
mapRef.setScaleControlsEnabled(true)   // 比例尺
mapRef.setZoomControlsEnabled(true)    // 缩放按钮

// 缩放
mapRef.zoomIn()
mapRef.zoomOut()

绘制折线

const mapRef = this.$refs['mapRef'] as PowBmapxElement

// 绘制普通折线
mapRef.drawPolyline(JSON.stringify({
    id: 'polyline001',
    points: [
        '116.362209,39.887487',
        '116.422897,39.878002',
        '116.372105,39.90651',
        '116.428945,39.89663'
    ],
    width: 10,
    color: '#FF0000',
    isDottedLine: false
}))

// 绘制纹理折线(需要base64纹理图片)
mapRef.drawTexturedPolyline(JSON.stringify({
    id: 'texturedPolyline001',
    points: [...],
    width: 20,
    texture: 'base64图片数据'
}))

// 删除折线
mapRef.removePolyline(JSON.stringify({ id: 'polyline001' }))
mapRef.removeAllPolylines()

绘制圆形

const mapRef = this.$refs['mapRef'] as PowBmapxElement

mapRef.drawCircle(JSON.stringify({
    id: 'circle001',
    lat: 39.91054,
    lng: 116.398111,
    radius: 1000,           // 半径(米)
    lineWidth: 5,
    strokeColor: '#FF0000',
    fillColor: '#50FF0000'  // 支持ARGB
}))

// 删除圆形
mapRef.removeCircle(JSON.stringify({ id: 'circle001' }))
mapRef.removeAllCircles()

绘制多边形

const mapRef = this.$refs['mapRef'] as PowBmapxElement

mapRef.drawPolygon(JSON.stringify({
    id: 'polygon001',
    points: [
        '116.404,39.915',
        '116.408,39.917',
        '116.412,39.919',
        '116.410,39.923',
        '116.406,39.923'
    ],
    lineWidth: 5,
    strokeColor: '#0000FF',
    fillColor: '#500000FF'
}))

// 删除多边形
mapRef.removePolygon(JSON.stringify({ id: 'polygon001' }))
mapRef.removeAllPolygons()

添加Marker

const mapRef = this.$refs['mapRef'] as PowBmapxElement

const markers = [
    {
        id: 'marker001',
        lat: 39.909187,
        lng: 116.397455,
        title: '天安门',
        icon: 'https://example.com/icon.png',  // 网络图片或base64
        iconWidth: 30,
        iconHeight: 30,
        iconRadius: 15,     // 圆角半径,设为宽高一半则为圆形
        anchor: 'center',   // 命名锚点,或使用 '0.5,1.0' 数字格式
        rotate: 0,          // 旋转角度(兼容旧字段 rotation)
        draggable: true,    // 是否可拖拽
        flat: false,        // 是否平贴地图(Android)
        zIndex: 10,         // 覆盖层级
        alpha: 0.9,         // 透明度,范围 0~1
        animateType: 'drop', // 'drop' | 'grow' | 'none'
        // 自定义气泡
        callout: {
            content: '这是气泡内容',
            textColor: '#333333',
            fontSize: 12,
            bgColor: '#FFFFFF',
            borderColor: '#CCCCCC',
            borderWidth: 1,
            borderRadius: 5,
            padding: 5,
            // 左侧图标
            leftIcon: {
                url: 'https://example.com/left.png',
                width: 24,
                height: 24
            },
            // 右侧图标
            rightIcon: {
                url: 'https://example.com/right.png',
                width: 24,
                height: 24
            }
        }
    },
    {
        id: 'marker002',
        lat: 39.929187,
        lng: 116.407455,
        icon: 'https://example.com/avatar.jpg',
        iconWidth: 60,
        iconHeight: 60,
        iconRadius: 30  // 圆形头像效果
    }
]

// 添加Markers
mapRef.addMarkers(JSON.stringify(markers))

// 删除指定Markers
mapRef.removeSomeMarkers(JSON.stringify([{ id: 'marker001' }]))

// 删除所有Markers
mapRef.removeAllMarkers()

// 缩放地图以包含所有Markers
mapRef.setVisibleIncludeMarkers(JSON.stringify({
    markers: markers,
    paddingTop: 50,
    paddingBottom: 50,
    paddingLeft: 50,
    paddingRight: 50,
    animated: true
}))

完整示例代码

示例页面一:功能入口页面

<template>
    <view class="container">
        <scroll-view class="scroll-area" scroll-y="true">
            <text class="title">系统功能</text>
            <view class="content">
                <button type="primary" size="mini" @click="checkPermission">检查定位权限</button>
                <button type="primary" size="mini" @click="goToMap">跳转到地图</button>
            </view>

            <text class="title">导航功能</text>
            <view class="content">
                <button type="primary" size="mini" @click="startDriveNavi">驾车导航</button>
                <button type="primary" size="mini" @click="startTruckNavi">货车导航</button>
                <button type="warn" size="mini" @click="stopNavi">停止导航</button>
            </view>

            <text class="title">定位功能</text>
            <view class="content">
                <button type="primary" size="mini" @click="singleLocation">单次定位</button>
                <button type="primary" size="mini" @click="startLocation">持续定位</button>
                <button type="primary" size="mini" @click="stopLocation">停止定位</button>
            </view>

            <text class="title">搜索功能</text>
            <view class="content">
                <button type="primary" size="mini" @click="searchPoi">关键词搜索</button>
                <button type="primary" size="mini" @click="searchNearby">周边搜索</button>
                <button type="primary" size="mini" @click="searchGeocode">地理编码</button>
                <button type="primary" size="mini" @click="searchRegeocode">逆地理编码</button>
            </view>

            <text class="title">路线规划</text>
            <view class="content">
                <button type="primary" size="mini" @click="searchDriveRoute">驾车路线</button>
                <button type="primary" size="mini" @click="searchWalkRoute">步行路线</button>
                <button type="primary" size="mini" @click="searchRideRoute">骑行路线</button>
            </view>

            <text class="title">工具功能</text>
            <view class="content">
                <button type="primary" size="mini" @click="calcDistance">计算距离</button>
                <button type="primary" size="mini" @click="calcArea">计算面积</button>
                <button type="primary" size="mini" @click="convertCoord">坐标转换</button>
            </view>

            <text class="title">TTS语音播报</text>
            <view class="content">
                <input class="voice-input" placeholder="输入播放文字" v-model="ttsText" />
            </view>
            <view class="content">
                <button type="primary" size="mini" @click="readTTS">播放</button>
                <button type="warn" size="mini" @click="stopTTS">停止</button>
            </view>
        </scroll-view>

        <view class="result-area">
            <text class="result-text">{{resultText}}</text>
        </view>
    </view>
</template>

<script lang="uts" setup>
import {
    initBmapSDK,
    checkAndRequestLocationPermission,
    getBmapLocation,
    startBmapLocation,
    stopBmapLocation,
    searchBmapPois,
    searchBmapGeocode,
    searchBmapRegeocode,
    bmapLineDistance,
    bmapCalculateArea,
    bmapCoordFromOtherCoord,
    speakText,
    stopSpeak,
    prepareNaviPermissions,
    initBmapNaviSDK,
    isBmapNaviInitialized,
    startBmapNavi,
    stopBmapNavi,
    searchBmapDriveRoute,
    searchBmapWalkRoute,
    searchBmapRideRoute
} from '@/uni_modules/pow-bmapx'

let resultText = ref('')
let ttsText = ref('百度地图语音测试')

onReady(() => {
    // 初始化SDK
    initBmapSDK('your_android_key')
})

const checkPermission = () => {
    checkAndRequestLocationPermission((res: UTSJSONObject) => {
        resultText.value = `权限结果: ${res['msg']}`
    })
}

const singleLocation = () => {
    getBmapLocation({ needAddress: true }, (res: UTSJSONObject) => {
        if (res['errCode'] == 0) {
            resultText.value = `定位: ${res['lat']}, ${res['lon']}`
        }
    })
}

const searchPoi = () => {
    searchBmapPois({
        keywords: ['餐厅'],
        lat: 39.91054,
        lon: 116.398111,
        radius: 5000
    }, (res: UTSJSONObject) => {
        if (res['errCode'] == 0) {
            const pois = res['pois'] as Array<UTSJSONObject>
            resultText.value = `找到 ${pois.length} 个结果`
        }
    })
}

const readTTS = () => {
    speakText(ttsText.value, 'zh', 0.55)
}

const stopTTS = () => {
    stopSpeak()
}
</script>

示例页面二:地图组件页面

<template>
    <view class="container">
        <view class="map-stack">
            <pow-bmapx
                ref="mapRef"
                class="native-map"
                :center="mapCenter"
                :zoomLevel="mapZoomLevel"
                @load="onMapLoad"
                @markerClick="onMarkerClick"
                @cameraChange="onCameraChange"
            ></pow-bmapx>
        </view>

        <scroll-view class="controls-area" scroll-y="true">
            <view class="section">
                <text class="section-title">地图控制</text>
                <view class="btns">
                    <button size="mini" type="primary" @click="moveCenter">移动中心点</button>
                    <button size="mini" type="primary" @click="zoomIn">放大</button>
                    <button size="mini" type="primary" @click="zoomOut">缩小</button>
                </view>
                <view class="btns">
                    <button size="mini" @click="setMapTypeNormal">普通地图</button>
                    <button size="mini" @click="setMapTypeSatellite">卫星地图</button>
                    <button size="mini" @click="toggleTraffic">路况</button>
                </view>
            </view>

            <view class="section">
                <text class="section-title">绘制功能</text>
                <view class="btns">
                    <button size="mini" type="primary" @click="drawPolyline">画折线</button>
                    <button size="mini" type="primary" @click="drawCircle">画圆形</button>
                    <button size="mini" type="primary" @click="drawPolygon">画多边形</button>
                    <button size="mini" type="warn" @click="clearAll">清除所有</button>
                </view>
            </view>

            <view class="section">
                <text class="section-title">Marker功能</text>
                <view class="btns">
                    <button size="mini" type="primary" @click="addMarkers">添加Markers</button>
                    <button size="mini" type="warn" @click="removeAllMarkers">删除所有</button>
                    <button size="mini" @click="zoomToFitMarkers">缩放包含</button>
                </view>
            </view>

            <view class="section">
                <text class="section-title">位置功能</text>
                <view class="btns">
                    <button size="mini" @click="toggleMyLocation">显示位置</button>
                    <button size="mini" @click="toggleFollowMode">跟随模式</button>
                </view>
            </view>
        </scroll-view>
    </view>
</template>

<script>
export default {
    data() {
        return {
            mapCenter: '116.398111,39.91054',
            mapZoomLevel: 12,
            trafficEnabled: false,
            myLocationEnabled: false,
            followMode: false,
            markersData: [
                {
                    id: 'marker001',
                    lat: 39.909187,
                    lng: 116.397455,
                    icon: 'https://example.com/icon.png',
                    iconWidth: 30,
                    iconHeight: 30,
                    callout: {
                        content: '天安门',
                        textColor: '#333333',
                        bgColor: '#ffffff',
                        borderRadius: 5,
                        padding: 5
                    },
                    draggable: true
                }
            ]
        }
    },
    methods: {
        onMapLoad() {
            console.log('地图加载完成')
        },
        onMarkerClick(e) {
            console.log('Marker点击:', e.detail)
        },
        onCameraChange(e) {
            console.log('视角变化:', e.detail)
        },
        moveCenter() {
            const lat = 39.9 + Math.random() * 0.1
            const lon = 116.3 + Math.random() * 0.2
            this.mapCenter = `${lon},${lat}`
        },
        zoomIn() {
            if (this.mapZoomLevel < 20) this.mapZoomLevel++
        },
        zoomOut() {
            if (this.mapZoomLevel > 3) this.mapZoomLevel--
        },
        setMapTypeNormal() {
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.setMapType(1)
        },
        setMapTypeSatellite() {
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.setMapType(2)
        },
        toggleTraffic() {
            this.trafficEnabled = !this.trafficEnabled
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.showTraffic(this.trafficEnabled)
        },
        drawPolyline() {
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.drawPolyline(JSON.stringify({
                id: 'polyline001',
                points: ['116.362209,39.887487', '116.422897,39.878002', '116.428945,39.89663'],
                width: 10,
                color: '#FF0000'
            }))
        },
        drawCircle() {
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.drawCircle(JSON.stringify({
                id: 'circle001',
                lat: 39.91054,
                lng: 116.398111,
                radius: 1000,
                strokeColor: '#FF0000',
                fillColor: '#50FF0000'
            }))
        },
        drawPolygon() {
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.drawPolygon(JSON.stringify({
                id: 'polygon001',
                points: ['116.404,39.915', '116.412,39.919', '116.406,39.923'],
                strokeColor: '#0000FF',
                fillColor: '#500000FF'
            }))
        },
        clearAll() {
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.removeAllPolylines()
            mapRef.removeAllCircles()
            mapRef.removeAllPolygons()
        },
        addMarkers() {
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.addMarkers(JSON.stringify(this.markersData))
        },
        removeAllMarkers() {
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.removeAllMarkers()
        },
        zoomToFitMarkers() {
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.setVisibleIncludeMarkers(JSON.stringify({
                markers: this.markersData,
                paddingTop: 50,
                paddingBottom: 50,
                paddingLeft: 50,
                paddingRight: 50,
                animated: true
            }))
        },
        toggleMyLocation() {
            this.myLocationEnabled = !this.myLocationEnabled
            const mapRef = this.$refs['mapRef'] as PowBmapxElement
            mapRef.showMyLocation(JSON.stringify({
                show: this.myLocationEnabled,
                mode: this.followMode ? 'following' : 'normal'
            }))
        },
        toggleFollowMode() {
            this.followMode = !this.followMode
            if (this.myLocationEnabled) {
                const mapRef = this.$refs['mapRef'] as PowBmapxElement
                mapRef.showMyLocation(JSON.stringify({
                    show: true,
                    mode: this.followMode ? 'following' : 'normal'
                }))
            }
        }
    }
}
</script>

<style>
.container {
    display: flex;
    flex-direction: column;
    height: 100%;
}
.map-stack {
    height: 50%;
    position: relative;
}
.native-map {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
.controls-area {
    flex: 1;
}
.section {
    padding: 10rpx 20rpx;
    background-color: #f8f8f8;
    margin-top: 10rpx;
}
.section-title {
    font-size: 28rpx;
    color: #666;
}
.btns {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    padding: 10rpx 0;
}
.btns button {
    margin: 5rpx;
}
</style>

百度鹰眼围栏告警

Android 与 iOS 使用完全相同的 JS API。首期仅支持服务端圆形、多边形围栏,输入坐标固定为百度经纬度 bd09ll

import {
    createYingyanFence,
    startYingyanFenceMonitor,
    stopYingyanFenceMonitor
} from '@/uni_modules/pow-bmapx'

const serviceOptions = {
    ak: 'your_android_or_ios_sdk_ak', // 当前平台的端侧 AK,不是服务端 AK
    serviceId: 123456,
    entityName: 'device-001'
}

// 创建服务端圆形围栏
createYingyanFence({
    ...serviceOptions,
    shape: 'circle',
    fenceName: 'warehouse',
    center: { lat: 39.91054, lng: 116.398111 },
    radius: 200,
    denoiseAccuracy: 0
}, (res) => {
    console.log('圆形围栏创建结果', res)
})

// 创建服务端多边形围栏,至少需要三个有效顶点
createYingyanFence({
    ...serviceOptions,
    shape: 'polygon',
    fenceName: 'operation-area',
    points: [
        { lat: 39.912, lng: 116.396 },
        { lat: 39.912, lng: 116.401 },
        { lat: 39.908, lng: 116.401 },
        { lat: 39.908, lng: 116.396 }
    ],
    denoiseAccuracy: 0
}, (res) => {
    console.log('多边形围栏创建结果', res)
})

// 启动鹰眼服务和轨迹采集。该回调会持续返回启动、告警、停止和错误事件。
startYingyanFenceMonitor({
    ...serviceOptions,
    keepAlive: true,
    gatherInterval: 5,
    packInterval: 10
}, (res) => {
    switch (res['type']) {
        case 'monitorStart':
            console.log('围栏监听已启动')
            break
        case 'fenceAlarm':
            console.log(
                res['action'],       // enter | exit
                res['fenceId'],
                res['fenceName'],
                res['entityName'],
                res['currentPoint'],
                res['previousPoint']
            )
            break
        case 'monitorStop':
            console.log('围栏监听已停止')
            break
        case 'error':
            console.log('围栏监听失败', res['stage'], res['errCode'], res['nativeCode'], res['errMsg'])
            break
    }
})

// 先停止轨迹采集,再停止鹰眼服务;monitorStop 从上面的持续回调返回。
stopYingyanFenceMonitor()

创建结果固定包含:

  • type: "createFenceResult"
  • errCodeerrMsgnativeCode
  • 成功时额外包含 fenceIdfenceNameshapefenceType: "server"

本地统一错误码:-1 参数错误、-2 重复启动或 service 配置冲突、-3 权限被拒绝、-4 SDK 初始化/鉴权/原生调用失败。具体 SDK 错误保留在 nativeCode

注意事项:

  • gatherIntervalpackInterval 范围均为 2~300 秒,packInterval 必须是 gatherInterval 的整数倍。
  • keepAlive 默认为 true。Android 会使用前台服务通知;iOS 需要“始终允许”定位权限。
  • 监听运行期间可以使用同一组 service 配置创建围栏;不同 ak/serviceId/entityName 会返回配置冲突,不会替换当前实例。
  • JS 告警回调仅保证 App 进程存活时可达。本版本不提供进程终止后的告警持久化或本地通知。
  • iOS 请使用真机验收;BaiduTraceKit 3.2.2 对模拟器架构存在限制。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率: