Android开发之新版百度map的调用(二):map中添加覆盖物及响应事件和弹出POP功能

本文详细介绍了在BaiduMap中添加覆盖物的方法,包括如何验证BaiduMap密钥、创建主地图和地图主控件,以及实现覆盖物的添加、编辑和删除功能。通过实例代码演示了如何在地图上添加标记、地面覆盖物,并提供了覆盖物的点击事件处理。同时,文章还介绍了如何清除和重新添加覆盖物,以及地图的生命周期管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天小木在这里给大家介绍在BaiduMap中添加覆盖物的方法,希望可以帮助到大家。


运行结果如图所示:




首先验证BaiduMap密钥的代码,DemoApplication.java:

<span style="font-size:18px;">package com.example.overlaydemo;

import android.app.Application;

import com.baidu.mapapi.SDKInitializer;

public class DemoApplication extends Application {

	@Override
	public void onCreate() {
		super.onCreate();
		// 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext
		SDKInitializer.initialize(this);
	}

}</span>


主地图MainActivity.java中的代码:

package com.example.overlaydemo;

import android.app.Activity;
import android.graphics.Point;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.GroundOverlayOptions;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.InfoWindow.OnInfoWindowClickListener;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.LatLngBounds;

/**
 * 演示覆盖物的用法
 */
public class MainActivity extends Activity {

	/**
	 * MapView 是地图主控件
	 */
	private MapView mMapView;
	private BaiduMap mBaiduMap;
	private Marker mMarkerA;
	private Marker mMarkerB;
	private Marker mMarkerC;
	private Marker mMarkerD;
	private InfoWindow mInfoWindow;

	// 初始化全局 bitmap 信息,不用时及时 recycle
	BitmapDescriptor bdA = BitmapDescriptorFactory
			.fromResource(R.drawable.icon_marka);
	BitmapDescriptor bdB = BitmapDescriptorFactory
			.fromResource(R.drawable.icon_markb);
	BitmapDescriptor bdC = BitmapDescriptorFactory
			.fromResource(R.drawable.icon_markc);
	BitmapDescriptor bdD = BitmapDescriptorFactory
			.fromResource(R.drawable.icon_markd);
	BitmapDescriptor bd = BitmapDescriptorFactory
			.fromResource(R.drawable.icon_gcoding);
	BitmapDescriptor bdGround = BitmapDescriptorFactory
			.fromResource(R.drawable.ground_overlay);

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mMapView = (MapView) findViewById(R.id.bmapView);
		mBaiduMap = mMapView.getMap();
		MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(14.0f);
		mBaiduMap.setMapStatus(msu);
		initOverlay();
		mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener() {
			public boolean onMarkerClick(final Marker marker) {
				Button button = new Button(getApplicationContext());
				button.setBackgroundResource(R.drawable.popup);
				final LatLng ll = marker.getPosition();
				Point p = mBaiduMap.getProjection().toScreenLocation(ll);
				p.y -= 47;
				LatLng llInfo = mBaiduMap.getProjection().fromScreenLocation(p);
				OnInfoWindowClickListener listener = null;
				if (marker == mMarkerA || marker == mMarkerD) {
					button.setText("更改位置");
					listener = new OnInfoWindowClickListener() {
						public void onInfoWindowClick() {
							LatLng llNew = new LatLng(ll.latitude + 0.005,
									ll.longitude + 0.005);
							marker.setPosition(llNew);
							mBaiduMap.hideInfoWindow();
						}
					};
				} else if (marker == mMarkerB) {
					button.setText("更改图标");
					listener = new OnInfoWindowClickListener() {
						public void onInfoWindowClick() {
							marker.setIcon(bd);
							mBaiduMap.hideInfoWindow();
						}
					};
				} else if (marker == mMarkerC) {
					button.setText("删除");
					listener = new OnInfoWindowClickListener() {
						public void onInfoWindowClick() {
							marker.remove();
							mBaiduMap.hideInfoWindow();
						}
					};
				}
				mInfoWindow = new InfoWindow(button, llInfo, listener);
				mBaiduMap.showInfoWindow(mInfoWindow);
				return true;
			}
		});
	}

	public void initOverlay() {
		// add marker overlay
		LatLng llA = new LatLng(39.963175, 116.400244);
		LatLng llB = new LatLng(39.942821, 116.369199);
		LatLng llC = new LatLng(39.939723, 116.425541);
		LatLng llD = new LatLng(39.906965, 116.401394);

		OverlayOptions ooA = new MarkerOptions().position(llA).icon(bdA)
				.zIndex(9);
		mMarkerA = (Marker) (mBaiduMap.addOverlay(ooA));
		OverlayOptions ooB = new MarkerOptions().position(llB).icon(bdB)
				.zIndex(5);
		mMarkerB = (Marker) (mBaiduMap.addOverlay(ooB));
		OverlayOptions ooC = new MarkerOptions().position(llC).icon(bdC)
				.perspective(false).anchor(0.5f, 0.5f).rotate(30).zIndex(7);
		mMarkerC = (Marker) (mBaiduMap.addOverlay(ooC));
		OverlayOptions ooD = new MarkerOptions().position(llD).icon(bdD)
				.perspective(false).zIndex(7);
		mMarkerD = (Marker) (mBaiduMap.addOverlay(ooD));

		// add ground overlay
		LatLng southwest = new LatLng(39.92235, 116.380338);
		LatLng northeast = new LatLng(39.947246, 116.414977);
		LatLngBounds bounds = new LatLngBounds.Builder().include(northeast)
				.include(southwest).build();

		OverlayOptions ooGround = new GroundOverlayOptions()
				.positionFromBounds(bounds).image(bdGround).transparency(0.8f);
		mBaiduMap.addOverlay(ooGround);

		MapStatusUpdate u = MapStatusUpdateFactory
				.newLatLng(bounds.getCenter());
		mBaiduMap.setMapStatus(u);
	}

	/**
	 * 清除所有Overlay
	 * 
	 * @param view
	 */
	public void clearOverlay(View view) {
		mBaiduMap.clear();
	}

	/**
	 * 重新添加Overlay
	 * 
	 * @param view
	 */
	public void resetOverlay(View view) {
		clearOverlay(null);
		initOverlay();
	}

	@Override
	protected void onPause() {
		// MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause()
		mMapView.onPause();
		super.onPause();
	}

	@Override
	protected void onResume() {
		// MapView的生命周期与Activity同步,当activity恢复时需调用MapView.onResume()
		mMapView.onResume();
		super.onResume();
	}

	@Override
	protected void onDestroy() {
		// MapView的生命周期与Activity同步,当activity销毁时需调用MapView.destroy()
		mMapView.onDestroy();
		super.onDestroy();
		// 回收 bitmap 资源
		bdA.recycle();
		bdB.recycle();
		bdC.recycle();
		bdD.recycle();
		bd.recycle();
		bdGround.recycle();
	}

}

 AndroidManifest.xml中的代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.overlaydemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="19" />

    <application
        android:name="com.example.overlaydemo.DemoApplication"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="开发者自己的密钥" />

        <activity
            android:name="com.example.overlaydemo.MainActivity"
            android:configChanges="orientation|keyboardHidden"
            android:label="@string/app_name"
            android:screenOrientation="sensor" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
         <service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote" >
        </service>
    </application>

    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />

    <permission android:name="android.permission.BAIDU_LOCATION_SERVICE" >
    </permission>

    <uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" >
    </uses-permission>
    <uses-permission android:name="android.permission.INTERNET" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" >
    </uses-permission>
    <!-- <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"></uses-permission> -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" >
    </uses-permission>
    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" >
    </uses-permission>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_GPS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <!-- SDK1.5需要android.permission.GET_TASKS权限判断本程序是否为当前运行的应用? -->
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.CAMERA" >
    </uses-permission>
    <uses-permission android:name="android.permission.RECORD_AUDIO" >
    </uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
    </uses-permission>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <!-- 来电消音 -->
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" >
    </uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="false"
        android:resizeable="true"
        android:smallScreens="true" />

</manifest>


注意:在运行时将AndroidManifest.xml中的密钥改为自己的密钥。genymotion不能显示地图,建议在AVD或者真机中运行。


以下是小木写的demo的下载地址:

http://download.youkuaiyun.com/detail/u013671350/7734651



若以上内容帮助到各位,请点个赞或者发个评论,您的鼓励是小木最大的动力!!!

vue.esm.js:629 [Vue warn]: Error in v-on handler: "TypeError: Cannot read properties of undefined (reading 'BMap')" found in ---> <ElButton> at packages/button/src/button.vue <BmMap> <BtAddrBaiDu> at src\views\modules\battery\mymqttequdetailsguiji.vue <ElMain> at packages/main/src/main.vue <ElContainer> at packages/container/src/main.vue <ElDialog> at packages/dialog/src/component.vue <Mymqttequdetails> at src\views\modules\battery\mymqttequdetails.vue <HomeNew2> at src\views\common\home_new2.vue <ElCard> at packages/card/src/main.vue <MainContent> at src\views\main-content3.vue <Main> at src\views\main.vue <App> at src\App.vue <Root>报错,分析代码如何修复正确:<template> <div> <baidu-map id="allmap" :center="center" :zoom="zoom" @ready="handler" style="height:9.45rem;width: 100%;" @click="getClickInfo" :scroll-wheel-zoom='true'> <div class="drawing-panel" style="z-index: 99;"> <button class = "btn" @click='play(1)' size="small">播放</button> <button class = "btn" @click='play(2)' size="small">暂停</button> <button class = "btn" @click='play(3)' size="small">停止</button> <!-- 时间筛选工具栏 --> <div> <div class="time-filter"> <el-date-picker v-model="startTime" type="datetime" placeholder="开始时间" format=yyyy-MM-dd HH:mm:ss value-format=yyyy-MM-dd HH:mm:ss /> <el-date-picker v-model="endTime" type="datetime" placeholder="结束时间" format=yyyy-MM-dd HH:mm:ss value-format=yyyy-MM-dd HH:mm:ss /> <el-button type="primary" @click="searchConfirm">查询</el-button> </div> </div> </div> </baidu-map> </div> </template> <script> export default { name: 'BtAddrBaiDu', data () { return { startTime: null, // 新增:开始时间 endTime: null, // 新增:结束时间 center: {lng: 114.085947, lat: 22.547}, zoom: 15, // 地图缩放比例,越大越细 point:"", gpsArr:[ { lng:114.000069, lat:22.500069 }, // { // lng:114.54050114953694, // lat:38.13759635572114 // }, // { // lng:114.56579743269792, // lat:38.12419932394176 // }, // { // lng:114.5908781225365, // lat:38.12056580319661 // }, // { // lng:114.6115750814864, // lat:38.11613720325717 // }, ],//后台拿到的gps点数组 speed:500,//速度 lushu:{},//路书 batteryId:"电池编号:"+this.$parent.$children[0].hwid, myMap: {} //地图 } }, mounted(){ this.handler(); // 函数调用 }, methods: { searchConfirm() { this.handler(); console.log("============") }, handler({BMap, map}){ this.$nextTick(()=>{ this.$http({ url: this.$http.adornUrl('/mqtt/mtgpslocationinfo/queryGpsLocationInfos'), method: 'get', params: this.$http.adornParams({ 'thingid': this.$parent.$children[0].hwid, //从父类的一个子类中获取hwid,子类中的hwid都是一样的 this.detailsparentmsg 'startTime': this.startTime, 'endTime': this.endTime }) }).then(({data}) => { //无论有无数,都要画出地图 map.enableScrollWheelZoom(new BMap.Point(114.085947, 22.547), 15); map.centerAndZoom(); var arrPois = []; if (data && data.code === 0) { const socitem = data.data if (socitem && socitem.length > 0) { let clng = socitem[socitem.length-1].longitude; let clat = socitem[socitem.length-1].latitude; // this.center = {lng: socitem[socitem.length-1].longitude, lat: socitem[socitem.length-1].latitude}; // 以最新经纬度为中心 this.center = {lng: clng, lat: clat}; //下方为打点代码------------------------------------------------- // var nowIcon = new BMap.Icon( // require("../../../assets/img/guiji2.png"), // new BMap.Size(47, 47), // { // anchor: new BMap.Size(22, 40), // imageOffset: new BMap.Size(0, 0) // } // ); // var myIcon = new BMap.Icon( // "http://developer.baidu.com/map/jsdemo/img/car.png", // new BMap.Size(52, 26), // { // anchor: new BMap.Size(27, 13) // } // ); //http://map.baidu.com/image/us_mk_icon.png //说明:要使用不同的图片,只需要修改图片偏移就可以了,第一行第一列图片是(0, 0 - 0 * 25),第行第一列图片是(0, 0 - 1 * 25)......以此类推就可以了 var myIcon = new BMap.Icon( require("../../../assets/img/markers.png"), // "http://api.map.baidu.com/img/markers.png", new BMap.Size(23, 25), { offset: new BMap.Size(10, 25), // 指定定位位置 imageOffset: new BMap.Size(0, 0 - 11 * 25) // 设置图片偏移 }); //打点图标样式------------------------------------------------------ for (let i = 0; i < socitem.length; i++) { var p0 = socitem[i].longitude; var p1 = socitem[i].latitude; // var checksum = makerArry[i].checksum; var point = new BMap.Point(p0, p1); //118.230272,33.482474 arrPois.push(point); //距离差距 var distance = this.getDistance(clat,clng, p1,p0); var content = "<table style='color: #FFF;'>"; // content = content + "<tr><td> 电池编号:"+socitem[i].hwid+"</td></tr>"; // content = content + "<tr><td> 所属:"+socitem[i].describe+"</td></tr>"; // content = content + "<tr><td> 经纬度:"+socitem[i].longitudeMark+socitem[i].longitude+","+socitem[i].latitudeMark+socitem[i].latitude+"</td></tr>"; // content = content + "<tr><td> 与最新点距离:"+distance.toFixed(2)+"m</td></tr>"; // content = content + "<tr><td> 时间:"+socitem[i].modifyTime+"</td></tr>"; // content += "</table>"; content = content + "<tr><td> 电池编号:"+socitem[i].thingId+"</td></tr>"; // content = content + "<tr><td> 电量:"+socitem[i].soc+" %</td></tr>"; content = content + "<tr><td> 经纬度:"+socitem[i].longitudedirectionValue+socitem[i].longitude+","+socitem[i].latitudedirectionValue+socitem[i].latitude+"</td></tr>"; content = content + "<tr><td> 与最新点距离:"+distance.toFixed(2)+"m</td></tr>"; content = content + "<tr><td> 时间:"+socitem[i].uploadTime+"</td></tr>"; content += "</table>"; // var infoMessage = "<br><div class='nodate'>无数据!</div><br><span class='reminder'>点击标记获取更多信息</span>"; //调用创建marker标记的方法, var marker = this.createMarker( point, content, socitem[i].thingId, i, myIcon ); map.addOverlay(marker) // 将标注添加地图中 var circle = new BMap.Circle(point, 6, { strokeColor: 'Red', strokeWeight: 8, strokeOpacity: 2, Color: 'Blue', fillColor: '#f03' }) map.addOverlay(circle) } } else { console.log('没有数据的显示') this.soctitle = '暂无数据显示' } } else { console.log('没有数据的显示') this.noneTitle = '没有数据~' } //绘制箭头及其样式 var sy = new BMap.Symbol(BMap_Symbol_SHAPE_BACKWARD_OPEN_ARROW, { scale: 0.3,//图标缩放大小 strokeColor:'#fff',//设置矢量图标的线填充颜色 strokeWeight: 1//设置线宽 }); var icons = new BMap.IconSequence(sy, '100%', '5%',false);//设置为true,可以对轨迹进行编辑 //画轨迹 var polyLine = new BMap.Polyline(arrPois, { // strokeColor: "blue", //设置颜色 strokeWeight: 2, //宽度 strokeOpacity: 0.5, //透明度,取值范围0 - 1 strokeColor:"#303133",//设置颜色 #4C7FED #303133 #18a45b enableEditing: false,//是否启用线编辑,默认为false enableClicking: false,//是否响应点击事件,默认为true icons:[icons] }); map.addOverlay(polyLine); //画轨迹结束 BMapLib.LuShu.prototype._move = function(initPos, targetPos, effect) { var pointsArr = [initPos, targetPos]; //点数组 var me = this, //当前的帧数 currentCount = 0, //步长,米/秒 timer = 10, step = this._opts.speed / (1000 / timer), //初始坐标 init_pos = this._projection.lngLatToPoint(initPos), //获取结束点的(x,y)坐标 target_pos = this._projection.lngLatToPoint(targetPos), //总的步长 count = Math.round(me._getDistance(init_pos, target_pos) / step); //显示折线 //如果想显示小车走过的痕迹,放开这段代码就行 this._map.addOverlay( new BMap.Polyline(pointsArr, { strokeColor: "#111", strokeWeight: 3, strokeOpacity: 0.5 }) ); // 画线 //如果小于1直接移动到下一点 if (count < 1) { // alert(count < 1); me._moveNext(++me.i); return; } // alert(count); me._intervalFlag = setInterval(function() { //两点之间当前帧数大于总帧数的时候,则说明已经完成移动 if (currentCount >= count) { clearInterval(me._intervalFlag); //移动的点已经超过总的长度 if (me.i > me._path.length) { return; } //运行下一个点 me._moveNext(++me.i); } else { currentCount++; var x = effect(init_pos.x, target_pos.x, currentCount, count), y = effect(init_pos.y, target_pos.y, currentCount, count), pos = me._projection.pointToLngLat(new BMap.Pixel(x, y)); //设置marker if (currentCount == 1) { var proPos = null; if (me.i - 1 >= 0) { proPos = me._path[me.i - 1]; } if (me._opts.enableRotation == true) { me.setRotation(proPos, initPos, targetPos); } if (me._opts.autoView) { if (!me._map.getBounds().containsPoint(pos)) { me._map.setCenter(pos); } } } //正在移动 me._marker.setPosition(pos); //设置自定义overlay的位置 me._setInfoWin(pos); } }, timer); }; // BMAP_ANCHOR_TOP_LEFT 表示控件定位于地图的左上角。 // BMAP_ANCHOR_TOP_RIGHT 表示控件定位于地图的右上角。 // BMAP_ANCHOR_BOTTOM_LEFT 表示控件定位于地图的左下角。 // BMAP_ANCHOR_BOTTOM_RIGHT 表示控件定位于地图的右下角。 //添加地图类型控件 // map.addControl(new BMap.MapTypeControl({anchor: BMAP_ANCHOR_TOP_RIGHT}));//右上角,默认地图控件 //地图混合 // map.addControl(new BMap.MapTypeControl({ // mapTypes:[ // BMAP_NORMAL_MAP, // BMAP_HYBRID_MAP // ]})); //添加缩略图控件 map.addControl(new BMap.OverviewMapControl({isOpen:true,anchor:BMAP_ANCHOR_BOTTOM_RIGHT})); //添加缩放平移控件 map.addControl(new BMap.NavigationControl()); //添加比例尺控件 map.addControl(new BMap.ScaleControl({anchor:BMAP_ANCHOR_TOP_LEFT})); //添加地图类型控件 // map.addControl(new BMap.MapTypeControl()); // 普通街道视图:BMAP_NORMAL_MAP // 三维视图:BMAP_PERSPECTIVE_MAP // 卫星视图:BMAP_SATELLITE_MAP // 卫星路网的混合视图:BMAP_HYBRID_MAP map.addControl(new BMap.MapTypeControl({mapTypes: [BMAP_NORMAL_MAP,BMAP_SATELLITE_MAP],anchor: BMAP_ANCHOR_TOP_RIGHT})); //负责切换地图类型的控件 this.initLushu(map, arrPois, this.batteryId); // map.addEventListener('tilesloaded', function () { // alert('地图加载完成!'); // }); }) }) }, // 测量百度地图两个点间的距离 // getDistance (itemPoint) { // var map = new BMap.Map('') // var pointB = new BMap.Point(parseFloat(itemPoint.log), parseFloat(itemPoint.lat)) // 店铺的经纬度 // var distance = (map.getDistance(this.pointA, pointB) / 1000).toFixed(2) // 保留小数点后两位 // return distance // }, /* * Lat1 Lung1 表示A点经纬度,Lat2 Lung2 表示B点经纬度; a=Lat1 – Lat2 为两点纬度之差 b=Lung1 * -Lung2 为两点经度之差; * 6378.137为地球半径,单位为公里; * 最新平均半径 大约3959英里(6371.393千米) 。这个数字是地心到地球表面所有各点距离的平均值。 可以这样求:平均半径=(赤道半径×2+极半径)/3 地球半径有时被使用作为距离单位, 特别是在天文学地质学中常用。它通常用RE表示。 地球大概半径6370.856千米。 * 计算出来的结果单位为公里。 * 经过经纬度获取距离(单位:公里) * @param lat1 * @param lng1 * @param lat2 * @param lng2 * @return */ getDistance(lat1,lng1,lat2,lng2) { let EARTH_RADIUS = 6378.137; let radLat1 = this.rad(lat1); let radLat2 = this.rad(lat2); let a = radLat1 - radLat2; let b = this.rad(lng1) - this.rad(lng2); let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); s = s * EARTH_RADIUS; // s = Math.round(s * 10000d) / 10000d; s = Math.round(s * 10000) / 10000; s = s*1000; //乘以1000是换算成米 return s; }, rad(d){ return d * Math.PI / 180.0; }, initLushu(map, arrPois, batteryId) { this.lushu = new BMapLib.LuShu(map, arrPois, { defaultContent: batteryId, // autoView: true, //是否开启自动视野调整,如果开启那么路书在运动过程中会根据视野自动调整 icon: new BMap.Icon( require("../../../assets/img/mybike2.png"), // "http://developer.baidu.com/map/jsdemo/img/car.png", // http://webapi.amap.com/images/car.png ~@/assets/img/car.png http://developer.baidu.com/map/jsdemo/img/fox.gif http://developer.baidu.com/map/jsdemo/img/car.png new BMap.Size(52, 26), { anchor: new BMap.Size(27, 13) } ), // icon: new BMap.Icon("http://developer.baidu.com/map/jsdemo/img/fox.gif", new BMap.Size(300,157)), speed: this.speed, enableRotation: true, //是否设置marker随着道路的走向进行旋转 landmarkPois: [ { lng:114.52785300795644, lat:38.14758574827796, html: "加油站", pauseTime: 2 } ] }); }, play(val) { // 动图播放 if (this.arrIndex >= this.gpsArr.length - 3) { this.arrIndex = 0; } switch (val) { case 1: this.lushu.start(); break; case 2: this.lushu.pause(); break; case 3: this.lushu.stop(); this.arrIndex = 0; this.percentage = 0; break; } }, //创建maekerinfowindow //传入的参数为:坐标,弹框中要显示的信息,厂区号 createMarker(point, iw, paramNumber,i,myIcon) { // var markerx = new BMap.Marker(point,{icon:myIcon}); var markerx = new BMap.Marker(point); //序号为1.2.3.4.....,根据需求更改 var label = new BMap.Label(i+1, { offset:new BMap.Size(-3,-5)}); label.setStyle({ background:'url()', // ~@/assets/img/guiji2.png color:'#fff', border:'none', fontSize:'12px', textAlign:'center', width:'25px', height:'25px', lineHeight:'25px' }); markerx.setLabel(label) //将序号放入标记中 markerx.setZIndex(9999) //在路线之上 覆盖路线 var opts = { width: 300, // 信息窗口宽度 height: 180, // 信息窗口高度 title: '<h4>坐标信息'+'</h4>', // 信息窗口标题 enableMessage: true, //设置允许信息窗发送短息 message: "" } //鼠标停留发生的事件 markerx.addEventListener("mouseover", function(e) { this.openInfoWindow(new BMap.InfoWindow(iw,opts)); // alert("mouseover==="+iw); }); //鼠标划出发生的事件 markerx.addEventListener("mouseout", function(e) { this.closeInfoWindow(new BMap.InfoWindow(iw)); }); //点击标记发生的事件,暂不做特殊处理 var that = this; markerx.addEventListener("click", function(e) { // this.openInfoWindow(new BMap.InfoWindow(iw,opts)); // that.$router.push({ // path: "home", // query: { // paramnumber: paramNumber // }//给跳转页面传递的参数 // }); }); return markerx; } }} </script> <style > /* 去除百度地图版权那行字 百度logo */ /* .BMap_cpyCtrl { display: none!important; } */ /* .anchorBL { display: none!important; } */ /* 弹出框中标题样式 */ .title { color: darkgreen; text-align: center; height: 0.125rem; } /* 弹出框中提示“无数据”的样式 */ .nodate { color: dimgrey; text-align: center; } /* 弹出框底部的点击提示样式 */ .reminder { font-size: 0.15rem; color: darkcyan; margin-left: 1.25rem; } .btn { width: 1.125rem; height: 0.375rem; float: left; background-color: #fff; color: rgba(27, 142, 236, 1); font-size: 0.175rem; border:0.0125rem solid rgba(27, 142, 236, 1); border-radius: 0.0625rem; margin: 0 0.0625rem; text-align: center; line-height: 0.375rem; } .btn:hover { background-color: rgba(27, 142, 236, 0.8); color: #fff; } .drawing-panel { z-index: 999; position: fixed; bottom: 1.3rem; margin-left: 0.3rem; padding: 0.12rem 0.12rem; border-radius: .05rem; background-color: #fff; box-shadow: 0 0.025rem 0.075rem 0 rgba(27, 142, 236, 0.5); } /* 以下为坐标 弹框信息的样式 */ /*地图标题*/ /* 去除百度地图版权那行字 百度logo */ /* .anchorBL, .BMap_cpyCtrl { display: none; } */ .BMap_bubble_title { color: white; font-size: 0.1625rem; font-weight: bold; text-align: left; padding-left: 0.0625rem; padding-top: 0.0625rem; border-bottom: 0.0125rem solid gray; background-color: #409EFF; } /* 消息内容 */ .BMap_bubble_content { background-color: rgba(40, 40, 40, 0.8); padding-left: 0.0625rem; padding-top: 0.0625rem; padding-bottom: 0.125rem; border-bottom-left-radius: 0.1rem; border-bottom-right-radius: 0.1rem; } /* 内容 */ .BMap_pop div:nth-child(9) { top: 0.4375rem !important; border-radius: 0.0625rem; } .BMap_pop div:nth-child(5) { display: none; } /* 左上角删除按键 */ .BMap_pop img { /* // top: 43px !important; // left: 215px !important; */ display: none; } .BMap_top { display: none; } .BMap_bottom { display: none; } .BMap_center { display: none; } /* 隐藏边角 */ .BMap_pop div:nth-child(1) div { display: none; } .BMap_pop div:nth-child(3) { display: none; } .BMap_pop div:nth-child(7) { display: none; } </style>
最新发布
08-21
<think>我们遇到的问题是:在Vue项目中使用了百度地图,并且出现了错误`vue.esm.js:629 [Vue warn]: Error in v-on handler: "TypeError: Cannot read properties of undefined (reading 'BMap')"`。 错误分析: 从错误信息来看,问题发生在事件处理函数中,尝试读取`BMap`属性时,发现其值为`undefined`。这通常意味着在访问`BMap`对象时,百度地图的API还没有加载完成。 观察代码,我们在`handler`方法中使用了`BMap``map`参数,这个方法是`<baidu-map>`组件的`@ready`事件处理函数。根据百度地图Vue组件(vue-baidu-map)的文档,`@ready`事件会传递一个包含`BMap`(百度地图命名空间)`map`(地图实例)的对象。 但是,在代码中,我们在`mounted`钩子中直接调用了`this.handler()`,此时可能百度地图还没有初始化完成,因此`BMap``map`都是`undefined`。 解决方案: 1. 避免在`mounted`中直接调用`handler`方法,因为地图可能还没有准备好。应该通过`@ready`事件来触发初始化。 2. 在`handler`方法中,我们使用了参数解构:`{BMap, map}`。但是,当我们直接调用`this.handler()`(比如在`mounted`中或者通过`searchConfirm`方法)时,没有传递任何参数,导致`BMap``map`都是`undefined`,从而引发错误。 因此,我们需要: - 移除`mounted`中调用`this.handler()`的代码,因为地图准备好后会通过`@ready`事件触发`handler`。 - 确保在需要重新加载数据时(比如点击查询按钮),我们能够正确地调用地图方法,但此时我们已经有地图实例了吗? 然而,在`searchConfirm`方法中,我们调用了`this.handler()`,同样没有传递参数。所以,我们需要改变思路: 建议: 1. 将地图实例BMap对象保存在组件的data属性中,这样在需要的时候(比如查询按钮点击)可以直接使用。 2. 在`@ready`事件中,我们调用`handler`并保存`BMap``map`实例。 3. 修改`handler`方法,使其不需要参数,而是使用已经保存的`BMap``map`实例。但是注意,第一次`@ready`事件触发时,我们保存了实例,然后进行数据加载地图绘制。而在查询按钮点击时,我们重新加载数据,使用保存的地图实例重新绘制。 具体步骤: 步骤1:在data中保存地图实例BMap对象 data() { return { ..., BMap: null, // 保存BMap命名空间 mapInstance: null, // 保存地图实例 } } 步骤2:在@ready事件中,将传入的BMapmap保存起来,并调用初始化方法(可以命名为initMap) <baidu-map ... @ready="onMapReady"> methods: { onMapReady({ BMap, map }) { this.BMap = BMap; this.mapInstance = map; this.initMap(); // 在这个方法中执行之前handler中的操作 } } 步骤3:将之前handler中的代码移动到initMap方法中,并且在这个方法中,使用this.BMapthis.mapInstance代替参数传入的BMapmap。 步骤4:修改searchConfirm方法,使其调用一个重新加载数据并绘制地图的方法(比如叫做loadDataAndDraw),而不是直接调用handler。 步骤5:在loadDataAndDraw方法中,我们使用已经保存的BMapmapInstance来重新绘制地图。注意,在绘制前需要清除之前的地图覆盖物(标记、折线等)。 步骤6:在组件中,我们不再需要直接调用handler,所以移除mounted中的调用。 但是,由于我们的代码中,handler方法内部还使用了this.$nextTick,并且调用了API获取数据,然后绘制地图。所以我们需要重构: 重构后的代码结构: 1. onMapReady({BMap, map}) 方法: - 保存BMapmap - 调用loadDataAndDraw() // 这个方法用于加载数据并绘制 2. loadDataAndDraw() 方法: - 使用保存的this.mapInstancethis.BMap - 清除地图上现有的覆盖物(如果有的话) - 发送请求获取数据 - 在获取数据后,进行绘制(包括标记、折线、路书等) 3. searchConfirm() 方法: - 调用loadDataAndDraw() 4. 移除mounted中的handler调用。 5. 注意:在第一次地图准备好后,会自动调用loadDataAndDraw。在查询按钮点击时,也会调用loadDataAndDraw。 另外,在loadDataAndDraw方法中,我们可能会遇到没有地图实例的情况(比如在第一次加载时,地图还没有准备好,但查询按钮被点击了)。所以,我们需要检查this.mapInstance是否存在。 修改代码示例: 由于代码较长,我们只修改关键部分: 在data中增加两个属性: BMap: null, mapInstance: null, 修改ready事件处理函数: handler({BMap, map}) { // 这里我们改名为onMapReady,但为了不引起混淆,我们先在模板中修改事件处理函数名为onMapReady this.BMap = BMap; this.mapInstance = map; this.loadDataAndDraw(); // 加载数据并绘制 } 然后,将原来handler中的代码(除了参数解构部分)移动到loadDataAndDraw方法中,并修改原来使用BMapmap的地方为this.BMapthis.mapInstance。 但是注意:原来的handler方法中使用了`BMapLib`,这个库是在百度地图加载后挂载在全局的,我们之前是通过`BMap`参数传入的,现在改为使用全局的`BMapLib`?或者我们可以在onMapReady中保存BMapLib?实际上,我们之前是使用`BMap`来访问`BMapLib`的,因为`BMapLib`是附加在`BMap`命名空间下的。但是,在代码中我们并没有显式传入`BMapLib`,所以我们需要确保在引入百度地图时已经加载了`BMapLib`(路书库)。 另外,在原来的代码中,我们修改了`BMapLib.LuShu.prototype._move`方法。这个修改只需要执行一次,所以我们可以将其放在`onMapReady`中,在`this.BMap`可用后修改。 因此,我们这样调整: 1. 将原来handler方法中的大部分代码移到loadDataAndDraw中,但修改原型的方法放在onMapReady中(确保只修改一次)。 2. 在onMapReady中,除了保存BMapmap,还要修改路书的原型方法(如果需要的话),然后调用loadDataAndDraw。 由于代码较长,我们逐步修改: 步骤: - 将原来的handler方法改名为onMapReady,并修改模板中的@ready="onMapReady" - 在onMapReady中,保存BMapmap,然后修改路书原型的_move方法(如果还需要的话),然后调用loadDataAndDraw - 创建loadDataAndDraw方法,将原来handler中$nextTick里面的代码移进去,并修改其中使用BMapmap的地方为this.BMapthis.mapInstance 注意:在loadDataAndDraw中,我们使用了this.$nextTick,这是为了确保DOM更新,但在地图操作中可能不是必须的,可以去掉,直接执行。 另外,在loadDataAndDraw中,我们需要清除地图上的所有覆盖物,可以使用this.mapInstance.clearOverlays(),但注意,百度地图的clearOverlays会清除所有覆盖物,包括我们后面添加的控件?不会,控件不会被清除。 所以,在每次绘制前,清除覆盖物。 修改后的代码结构如下: 由于代码较长,我们只展示修改后的关键部分: 注意:以下代码为修改后的部分,并非完整代码。 ```javascript export default { data() { return { // ...原有数据 BMap: null, // 保存BMap命名空间 mapInstance: null, // 保存地图实例 } }, mounted() { // 移除 this.handler(); // 不再需要 }, methods: { onMapReady({ BMap, map }) { this.BMap = BMap; this.mapInstance = map; // 修改路书原型的_move方法(如果需要的话) this.patchLushuPrototype(); // 初始加载数据 this.loadDataAndDraw(); }, patchLushuPrototype() { // 将原来handler中修改BMapLib.LuShu.prototype._move的代码移到这里 if (this.BMap && this.BMap.BMapLib) { this.BMap.BMapLib.LuShu.prototype._move = function(initPos, targetPos, effect) { // ...原代码 }; } }, searchConfirm() { this.loadDataAndDraw(); }, loadDataAndDraw() { // 如果地图实例不存在,则不能绘制 if (!this.mapInstance || !this.BMap) { console.error('地图未初始化'); return; } // 清除现有覆盖物(标记、折线等) this.mapInstance.clearOverlays(); // 发送请求获取数据 this.$http({ // ...参数不变 }).then(({data}) => { // 使用this.mapInstancethis.BMap代替原来的mapBMap const map = this.mapInstance; const BMap = this.BMap; // 原有的代码,但将mapBMap替换为this.mapInstancethis.BMap // 例如:map.enableScrollWheelZoom(new BMap.Point(114.085947, 22.547), 15); // 注意:在创建点、图标等时,都要使用BMap // ... 其他代码不变 // 在绘制完成后,初始化路书 this.initLushu(map, arrPois, this.batteryId); // ... 其他代码 }); }, // 其他方法保持不变 } } ``` 注意:在loadDataAndDraw方法中,我们使用了const map = this.mapInstance; const BMap = this.BMap; 是为了在回调函数中避免this指向问题,也可以使用箭头函数。 另外,在初始化路书(initLushu)时,我们传入的map应该是当前地图实例,arrPois是点数组,batteryId是电池编号。 由于我们每次查询都会重新获取数据并绘制,所以需要清除之前的地图覆盖物,然后重新绘制。 但是,在原来的代码中,我们除了绘制标记折线,还添加了控件(如缩放控件、比例尺等)。注意,clearOverlays会清除覆盖物,但不会清除控件。而且,我们在每次绘制时都重新添加控件,这会导致重复添加。所以,我们应该将控件的添加放在onMapReady中,只添加一次。 因此,我们需要调整: 在onMapReady中,添加控件(这些控件只需要添加一次): // 添加缩略图控件 map.addControl(new BMap.OverviewMapControl({isOpen:true,anchor:BMAP_ANCHOR_BOTTOM_RIGHT})); // 添加缩放平移控件 map.addControl(new BMap.NavigationControl()); // 添加比例尺控件 map.addControl(new BMap.ScaleControl({anchor:BMAP_ANCHOR_TOP_LEFT})); // 添加地图类型控件 map.addControl(new BMap.MapTypeControl({mapTypes: [BMAP_NORMAL_MAP,BMAP_SATELLITE_MAP],anchor: BMAP_ANCHOR_TOP_RIGHT})); 然后,在loadDataAndDraw中,不再添加控件。 这样修改后,控件只添加一次,不会重复。 最后,我们还需要注意一个问题:在第一次加载时,地图准备好后会自动调用onMapReady,然后加载数据并绘制。在查询按钮点击时,我们重新加载数据绘制,此时不需要再添加控件。 所以,我们将控件的添加移到onMapReady中,在patchLushuPrototype之后,loadDataAndDraw之前。 修改后的onMapReady方法: ```javascript onMapReady({ BMap, map }) { this.BMap = BMap; this.mapInstance = map; // 修改路书原型的_move方法 this.patchLushuPrototype(); // 添加控件(只添加一次) // 注意:这里使用BMapmap map.addControl(new BMap.OverviewMapControl({isOpen:true,anchor: BMap.ANCHOR_BOTTOM_RIGHT})); map.addControl(new BMap.NavigationControl()); map.addControl(new BMap.ScaleControl({anchor: BMap.ANCHOR_TOP_LEFT})); map.addControl(new BMap.MapTypeControl({mapTypes: [BMAP_NORMAL_MAP, BMAP_SATELLITE_MAP], anchor: BMap.ANCHOR_TOP_RIGHT})); // 初始加载数据 this.loadDataAndDraw(); }, ``` 注意:在添加控件时,使用了BMap.ANCHOR_...,这里注意大小写,原来代码中写的是BMAP_ANCHOR_...,但实际上是BMap.ANCHOR_...(因为BMap是命名空间,而BMAP_ANCHOR_...是常量,但百度地图API中这些常量是挂载在BMap上的,所以应该写为BMap.ANCHOR_BOTTOM_RIGHT等)。 但是,在百度地图JavaScript API中,这些常量是作为BMap的静态属性存在的,例如:BMap.ANCHOR_TOP_LEFT。所以,我们修改为BMap.ANCHOR_...。 同时,地图类型常量也是BMap的静态属性,例如:BMap.NORMAL_MAP,所以修改为: mapTypes: [BMap.NORMAL_MAP, BMap.SATELLITE_MAP] 因此,控件添加部分修改为: ```javascript map.addControl(new BMap.OverviewMapControl({isOpen:true, anchor: BMap.ANCHOR_BOTTOM_RIGHT})); map.addControl(new BMap.NavigationControl()); map.addControl(new BMap.ScaleControl({anchor: BMap.ANCHOR_TOP_LEFT})); map.addControl(new BMap.MapTypeControl({mapTypes: [BMap.NORMAL_MAP, BMap.SATELLITE_MAP], anchor: BMap.ANCHOR_TOP_RIGHT})); ``` 这样修改后,应该可以避免重复添加控件,并且只在初始化时添加一次。 最后,在loadDataAndDraw方法中,我们只需要清除覆盖物,然后重新绘制标记、折线、路书等。 由于修改较大,请仔细测试。 如果问题仍然存在,请检查BMapLib是否已经正确加载。在onMapReady中,我们修改了BMapLib.LuShu.prototype._move,但是BMapLib可能是在百度地图API加载后挂载在window上的,而不是BMap的命名空间下。所以,我们需要确认如何引入BMapLib。 通常,在使用路书功能时,我们需要额外引入路书库。在项目中,我们可能已经通过script标签引入了路书库,例如: <script src="http://api.map.baidu.com/library/LuShu/1.2/src/LuShu_min.js"></script> 然后,在组件中,我们通过全局的BMapLib来访问。所以,在组件中,我们不需要通过BMap来访问BMapLib,而是直接使用window.BMapLib。 因此,在patchLushuPrototype方法中,我们可以这样修改: ```javascript patchLushuPrototype() { if (window.BMapLib && window.BMapLib.LuShu) { window.BMapLib.LuShu.prototype._move = function(initPos, targetPos, effect) { // ...原代码 }; } }, ``` 同时,在initLushu方法中,我们也要使用window.BMapLib: ```javascript initLushu(map, arrPois, batteryId) { this.lushu = new window.BMapLib.LuShu(map, arrPois, { // ...参数 }); }, ``` 这样修改后,应该可以正确使用路书库。 总结修改点: 1. 移除mounted中的handler调用。 2. 将@ready绑定到onMapReady方法,在该方法中保存BMapmap实例,并添加控件(只添加一次),然后调用loadDataAndDraw。 3. 将原来handler中的代码移动到loadDataAndDraw,并修改为使用保存的BMapmapInstance。 4. 将修改路书原型的代码单独放在patchLushuPrototype方法中,并在onMapReady中调用。 5. 在查询按钮点击时,调用loadDataAndDraw重新加载数据并绘制。 6. 在loadDataAndDraw中,先清除地图上的覆盖物,再重新绘制。 7. 使用全局的window.BMapLib来操作路书。 由于代码较长,无法一一测试,请根据实际情况调整。 如果按照上述修改后,应该可以解决BMap未定义的问题,同时确保地图操作在正确初始化后进行。 注意:在模板中,我们已经将@ready="handler"修改为@ready="onMapReady",所以需要将handler方法改名为onMapReady,或者保留handler方法名但将@ready绑定为onMapReady(在模板中修改)。 在提供的代码中,模板中@ready绑定的是handler,所以我们需要将handler方法改名为onMapReady,或者将模板中的@ready="handler"改为@ready="onMapReady"。 我们选择在模板中修改: 原:@ready="handler" 改为:@ready="onMapReady" 同时,将原来的handler方法改名为onMapReady。 最后,由于修改了路书原型的_move方法,如果不再需要,可以移除。但根据原代码,可能是为了解决路书运动的问题,所以保留。 请根据上述步骤进行修改,应该可以解决问题。</think>根据错误信息`TypeError: Cannot read properties of undefined (reading 'BMap')`,问题出在百度地图API未正确加载时尝试访问`BMap`对象。以下是修复方案: ### 主要问题分析 1. **BMap未定义**:`handler()`方法在`mounted`中直接调用,此时百度地图API可能尚未加载完成 2. **参数未传递**:`searchConfirm()`调用`handler()`时未传递必要参数 3. **依赖加载顺序**:路书库`BMapLib`可能未正确加载 ### 修复代码 ```vue <script> export default { name: 'BtAddrBaiDu', data() { return { // ...原有数据 isMapReady: false, // 新增地图就绪状态标识 BMapObj: null, // 保存BMap实例 mapObj: null // 保存地图实例 } }, mounted() { // 移除直接调用handler() }, methods: { // 修改ready事件处理函数 handler({BMap, map}) { this.BMapObj = BMap; this.mapObj = map; this.isMapReady = true; this.loadMapData(); // 加载数据 }, // 新增数据加载方法 loadMapData() { if (!this.isMapReady) return; this.$http({ // ...请求参数不变 }).then(({data}) => { // 使用保存的实例 const BMap = this.BMapObj; const map = this.mapObj; // 原有地图操作代码... }); }, searchConfirm() { this.loadMapData(); // 使用统一加载方法 }, // 修改路书初始化方法 initLushu(map, arrPois, batteryId) { // 确保BMapLib已加载 if (typeof BMapLib === 'undefined') { console.error('BMapLib not loaded'); return; } this.lushu = new BMapLib.LuShu(map, arrPois, { // ...配置不变 }); }, // 其他方法保持不变... } } </script> ``` ### 关键修复点 1. **地图就绪状态管理**: - 添加`isMapReady`标志位 - 在`@ready`事件中设置`isMapReady=true` - 所有地图操作前检查`isMapReady` 2. **BMap实例保存**: - 在`handler()`中保存`BMap``map`实例 - 后续操作使用保存的实例 3. **统一数据加载**: - 创建`loadMapData()`方法处理数据加载 - `searchConfirm()``handler()`都调用此方法 4. **路书库加载检查**: - 使用`BMapLib`前检查`typeof BMapLib !== 'undefined'` - 确保在`index.html`中正确引入路书库: ```html <script src="https://api.map.baidu.com/library/LuShu/1.2/src/LuShu_min.js"></script> ``` 5. **移除直接调用**: - 删除`mounted()`中的`this.handler()` - 完全依赖`@ready`事件触发 ### 注意事项 1. 确保在`public/index.html`中正确加载百度地图API: ```html <script src="https://api.map.baidu.com/api?v=3.0&ak=您的AK&s=1"></script> ``` 2. 样式调整:路书图标路径使用绝对路径更可靠 ```js icon: new BMap.Icon( "/static/img/mybike2.png", // 改为绝对路径 new BMap.Size(52, 26) ) ``` 3. 错误处理:添加API加载失败的回调 ```html <script> window.baiduMapInit = function() { console.log('BMap API loaded'); } </script> <script src="https://api.map.baidu.com/api?v=3.0&ak=您的AK&callback=baiduMapInit" onerror="console.error('BMap load failed')"> </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值