补充地图的演示功能

This commit is contained in:
2025-11-24 14:49:07 +08:00
parent 38d08ad613
commit 9e8df74622
12 changed files with 599 additions and 16 deletions

View File

@@ -1,18 +1,127 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:geolocator/geolocator.dart';
import 'package:getx_scaffold/getx_scaffold.dart';
import 'package:permission_handler/permission_handler.dart'; // 确保引用这个做权限请求
class MapController extends GetxController with BaseControllerMixin {
@override
String get builderId => 'map';
MapController();
InAppWebViewController? webViewController;
StreamSubscription<Position>? positionStream;
final RxBool isLocationPermissionGranted = false.obs;
// 缓存最后一次的位置,防止 WebView 加载慢于定位
Position? _lastKnownPosition;
// 是否已经初始化过地图中心
bool _hasInitializedMapCenter = false;
@override
void onInit() {
super.onInit();
requestLocationPermission();
}
@override
void onClose() {
positionStream?.cancel();
super.onClose();
}
}
// 请求权限
void requestLocationPermission() async {
var status = await Permission.locationWhenInUse.request();
print("权限状态: $status"); // 在控制台看这个输出
if (status.isGranted) {
isLocationPermissionGranted.value = true;
showToast('定位权限已获取');
_startLocationTracking();
}
else if (status.isPermanentlyDenied) {
// iOS 特性:如果你之前点过“不允许”,之后再请求都会直接进这里
isLocationPermissionGranted.value = false;
// 引导用户去设置页面开启
openAppSettings();
}
else {
// 第一次被拒绝,或者其他情况
isLocationPermissionGranted.value = false;
showErrorToast('需要定位权限才能显示您的位置');
}
}
// 开启定位监听
void _startLocationTracking() async {
// 再次检查服务是否开启
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
return;
}
const LocationSettings locationSettings = LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 50, // 移动更新范围
);
// 先获取一次当前位置,用于快速初始化中心
Geolocator.getCurrentPosition().then((position) {
_lastKnownPosition = position;
_syncLocationToMap(position, isInit: true);
});
// 持续监听
positionStream = Geolocator.getPositionStream(locationSettings: locationSettings)
.listen((Position position) {
_lastKnownPosition = position;
_syncLocationToMap(position, isInit: false);
});
}
// 将位置同步给 JS
void _syncLocationToMap(Position position, {required bool isInit}) {
if (webViewController == null) return;
// 如果是第一次定位,或者 WebView 刚加载完且从未设置过中心
if (isInit || !_hasInitializedMapCenter) {
webViewController!.evaluateJavascript(
source: "initLocation(${position.latitude}, ${position.longitude})"
);
_hasInitializedMapCenter = true;
} else {
// 后续只更新图标位置,不强行移动地图中心(防止用户拖动地图看别处时被拉回)
webViewController!.evaluateJavascript(
source: "updateMyLocation(${position.latitude}, ${position.longitude}, ${position.heading})"
);
}
}
// WebView 加载完成回调
void onWebViewLoadStop() {
// 页面加载完了,如果我们已经拿到了定位数据,立刻设置地图中心
if (_lastKnownPosition != null) {
_syncLocationToMap(_lastKnownPosition!, isInit: true);
}
// 如果业务需要,可以在这里加载默认的推荐路径
// loadRecommendedRoute();
}
// 模拟:获取你的后台推荐路径
void loadRecommendedRoute() {
// 示例数据
List<List<double>> routePoints = [
[116.397428, 39.90923],
[116.398000, 39.90950],
[116.400000, 39.91000],
];
String jsonPoints = jsonEncode(routePoints);
webViewController?.evaluateJavascript(source: "drawCustomRoute($jsonPoints)");
}
}

View File

@@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:getx_scaffold/getx_scaffold.dart';
import 'controller.dart';
@@ -6,11 +6,32 @@ import 'controller.dart';
class MapPage extends GetView<MapController> {
const MapPage({super.key});
// 主视图
Widget _buildView() {
return <Widget>[
TextX.titleLarge('地图'),
].toColumn(mainAxisSize: MainAxisSize.min).center();
return Stack(
children: [
InAppWebView(
// 确保 pubspec.yaml 中声明了 assets/html/map.html
initialFile: 'assets/html/map.html',
initialSettings: InAppWebViewSettings(
isInspectable: true,
geolocationEnabled: true,
// 允许 JS 弹窗 (Alert) 用于调试
javaScriptCanOpenWindowsAutomatically: true,
),
onWebViewCreated: (c) {
controller.webViewController = c;
},
onLoadStop: (c, url) {
// 通知 Controller 页面加载完毕
controller.onWebViewLoadStop();
},
onConsoleMessage: (controller, consoleMessage) {
// 方便在 Flutter 控制台看 JS 日志
print("JS Log: ${consoleMessage.message}");
},
),
],
);
}
@override