flutter中使用webview对接百度地图JS_SDK

适用于 flutter 3.3.4

安装依赖

1
2
3
flutter_inappwebview: ^5.7.2+3
geolocator: ^8.2.1
permission_handler: ^9.2.0

配置 assets

1
2
3
flutter:
assets:
- assets/static/baidu-map-html/

在项目对应位置创建 index.html,复制下面的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Baidu Map</title>
<style type="text/css">
html {
height: 100%;
}
body {
height: 100%;
margin: 0px;
padding: 0px;
}
#container {
height: 100%;
}
</style>
<script
type="text/javascript"
src="https://api.map.baidu.com/api?v=3.0&ak=填写你自己的ak"
></script>
</head>
<body>
<div id="container"></div>
<script>
var map = new BMap.Map("container", {
coordsType: 5, // coordsType指定输入输出的坐标类型,3为gcj02坐标,5为bd0ll坐标,默认为5。
// 指定完成后API将以指定的坐标类型处理您传入的坐标
}); // 创建地图实例
var point = new BMap.Point(120.733491, 31.263752); // 创建点坐标
map.centerAndZoom(point, 15); // 初始化地图,设置中心点坐标和地图级别
map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
</script>
</body>
</html>

geolocator 配置

创建一个 dart 文件

初始化地图,使用 callAsyncJavaScript 注入脚本,实现地图操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import 'dart:convert';
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:geolocator/geolocator.dart';

class WebviewBaiduMap extends StatefulWidget {
final Map<String, dynamic> data;
const WebviewBaiduMap({Key? key, required this.data}) : super(key: key);

@override
State<WebviewBaiduMap> createState() => _WebviewBaiduMapState();
}

class _WebviewBaiduMapState extends State<WebviewBaiduMap> {
@override
Widget build(BuildContext context) {
InAppWebViewController? mapViewController;
const String htmlUrl = 'assets/static/baidu-map-html/index.html';

/// 申请定位权限
/// 授予定位权限返回true, 否则返回false
Future<bool> requestLocationPermission() async {
//获取当前的权限
var status = await Permission.location.status;
if (status == PermissionStatus.granted) {
//已经授权
return true;
} else {
//未授权则发起一次申请
status = await Permission.location.request();
if (status == PermissionStatus.granted) {
return true;
} else {
return false;
}
}
}

// ? 获取用户位置
void _getUserLocation() async {
bool hasLocationPermission = await requestLocationPermission();
if (!hasLocationPermission) return;
Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
final newLocal = GpsUtil.gps84_To_bd09(position.latitude, position.longitude);
// 获取定位后添加用户位置
mapViewController?.callAsyncJavaScript(
functionBody: '''
var userPoint = new BMap.Point(longitude, latitude);
var marker = new BMap.Marker(userPoint);
map.addOverlay(marker);
''',
arguments: {
'latitude': newLocal[0],
'longitude': newLocal[1],
},
);
}

// ? 获取车辆位置
void _getVehicleLocation({bool? setCenter}) {
final data = widget.data;
List<double> newLocal = [31.2660528, 120.7407351];

mapViewController?.callAsyncJavaScript(
functionBody: '''
var point = new BMap.Point(longitude, latitude);
var marker = new BMap.Marker(point);
map.addOverlay(marker); // 添加标记
map.panTo(point); // 地图中心点移动到指定位置
''',
arguments: {
'latitude': newLocal[0],
'longitude': newLocal[1],
},
);
}

return Scaffold(
resizeToAvoidBottomInset: false,
body: ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: Stack(
fit: StackFit.expand,
children: [
SizedBox(
width: double.infinity,
height: double.infinity,
child: InAppWebView(
initialFile: htmlUrl,
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(javaScriptEnabled: true),
android: AndroidInAppWebViewOptions(),
ios: IOSInAppWebViewOptions(),
),
onWebViewCreated: ((controller) {
log('网页创建');
}),
onProgressChanged: ((controller, progress) {
log('load $progress');
}),
onLoadStart: ((controller, url) {
log('load start $url');
}),
onLoadStop: ((controller, url) {
log('load stop $url');
setState(() {
mapViewController = controller;
});
_getVehicleLocation();
_getUserLocation();
}),
onLoadHttpError: ((controller, url, statusCode, description) {
log('$url $description');
}),
onLoadError: ((controller, url, code, message) {
log('$url $message');
}),
onLoadResource: ((controller, resource) {
log('load resource');
}),
),
),
const Positioned(
top: 0,
left: 0,
right: 0,
// 这里可以在右上角放一个返回按钮
child: Container(),
),
],
),
),
);
}
}