调整地图样式

This commit is contained in:
2025-11-27 15:25:58 +08:00
parent aa30d13b91
commit da4149ec60
3 changed files with 384 additions and 263 deletions

View File

@@ -1,13 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>路径规划</title>
<style>
html, body, #container { width: 100%; height: 100%; margin: 0; }
/* 搜索栏样式 */
<style>
/* --- 全局样式 --- */
html,
body,
#container {
width: 100%;
height: 100%;
margin: 0;
font-family: sans-serif;
}
/* --- 暴力隐藏高德自带的导流链接和Logo (关键) --- */
.amap-callamap,
.amap-lib-driving-callBtn,
.amap-copyright,
.amap-logo {
display: none !important;
}
#panel .amap-call {
display: none;
}
/* --- 搜索栏样式 --- */
#search-box {
position: absolute;
top: 10px;
@@ -16,227 +38,318 @@
z-index: 100;
background: #fff;
padding: 10px;
border-radius: 4px;
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
display: flex;
flex-direction: column;
gap: 8px;
}
.input-row { display: flex; gap: 5px; }
input { flex: 1; padding: 8px; border: 1px solid #eee; border-radius: 4px; }
button { padding: 0 15px; background: #3366FF; color: #fff; border: none; border-radius: 4px; font-weight: bold; }
/* 导航结果面板 (仿高德原生) */
.input-row {
display: flex;
gap: 8px;
align-items: center;
}
input {
flex: 1;
padding: 10px;
border: 1px solid #eee;
border-radius: 4px;
background-color: #f9f9f9;
font-size: 14px;
}
button {
padding: 0 15px;
height: 38px;
background: #3366FF;
color: #fff;
border: none;
border-radius: 4px;
font-weight: bold;
font-size: 14px;
}
/* --- 导航结果面板 (底部弹出) --- */
#panel {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 30%; /* 占据底部30% */
height: 35%;
/* 面板高度 */
background-color: white;
overflow-y: auto;
border-top: 1px solid #ccc;
border-top: 1px solid #eee;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
z-index: 99;
display: none; /* 默认隐藏,规划成功后显示 */
display: none;
/* 默认隐藏 */
}
/* --- 自定义定位按钮样式 --- */
#location-btn {
position: fixed;
right: 10px;
bottom: 50px;
/* 默认位置 */
width: 44px;
height: 44px;
background-color: #fff;
border-radius: 50%;
/* 圆形更符合现代审美 */
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
z-index: 150;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: bottom 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
/* 平滑动画 */
}
#location-btn:active {
background-color: #f2f2f2;
}
#location-btn svg {
width: 24px;
height: 24px;
fill: #555;
}
/* --- 关键:当 body 有 panel-active 类时,按钮上移 --- */
body.panel-active #location-btn {
bottom: 38%;
/* 对应 #panel 的 height + 一点间距 */
}
</style>
<!-- 1. 必须最先配置安全密钥 -->
<!-- 1. 配置安全密钥 -->
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode: '0529b72df6bf0c577ff2182cb8b1d970',
}
</script>
<!-- 2. 加载地图和插件 -->
<script src="https://webapi.amap.com/maps?v=2.0&key=2cc1d822e313307fe311c3127a1deeb5&plugin=AMap.MoveAnimation,AMap.Driving,AMap.TruckDriving,AMap.AutoComplete,AMap.ToolBar,AMap.Geolocation,AMap.Scale"></script>
<!-- 2. 加载地图和插件 (去掉了 Geolocation 插件,避免弹窗) -->
<script
src="https://webapi.amap.com/maps?v=2.0&key=2cc1d822e313307fe311c3127a1deeb5&plugin=AMap.MoveAnimation,AMap.Driving,AMap.TruckDriving,AMap.AutoComplete,AMap.ToolBar,AMap.Scale">
</script>
</head>
<body>
<div id="search-box">
<div class="input-row">
<input id="startInput" placeholder="起点: 默认使用当前位置"/>
<div id="search-box">
<div class="input-row">
<input id="startInput" placeholder="起点: 默认使用当前位置" readonly />
</div>
<div class="input-row">
<input id="endInput" placeholder="终点: 请输入目的地" />
<button onclick="startRouteSearch()">路径规划</button>
</div>
</div>
<div class="input-row">
<input id="endInput" placeholder="终点: 请输入目的地"/>
<button onclick="startRouteSearch()">路径规划</button>
<div id="container"></div>
<div id="panel"></div>
<!-- 自定义定位按钮 -->
<div id="location-btn" onclick="backToLocation()">
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<path
d="M512 85.333333a426.666667 426.666667 0 1 0 0 853.333334 426.666667 426.666667 0 0 0 0-853.333334z m0 149.333334a277.333333 277.333333 0 1 1 0 554.666666 277.333333 277.333333 0 0 1 0-554.666666z m0 149.333333a128 128 0 1 0 0 256 128 128 0 0 0 0-256z"
fill="#666666"></path>
</svg>
</div>
</div>
<div id="container"></div>
<div id="panel"></div>
<script>
var map, marker, driving, truckDriving;
var currentLat, currentLng;
var isTruckMode = false;
<script>
var map, marker, driving, truckDriving;
var currentLat, currentLng;
function initMap() {
map = new AMap.Map('container', {
resizeEnable: true,
zoom: 15,
viewMode: '3D'
});
// 标记是否使用货车模式 (true: 货车, false: 轿车)
var isTruckMode = false;
// 通知 Flutter 地图加载完毕
map.on('complete', function () {
console.log("JS->: Map is ready.");
if (window.flutter_inappwebview) {
window.flutter_inappwebview.callHandler('mapReady');
}
});
function initMap() {
map = new AMap.Map('container', {
resizeEnable: true,
zoom: 15,
viewMode: '3D'
});
// 添加基础控件
map.addControl(new AMap.Scale());
map.addControl(new AMap.ToolBar({
visible: true,
position: {
top: '200px',
right: '10px'
} // 稍微避开定位按钮
}));
// --- 新增:添加地图控件 ---
map.addControl(new AMap.Scale()); // 比例尺
map.addControl(new AMap.ToolBar({
position: {
bottom: '80px',
right: '10px'
}
})); // 缩放
map.addControl(new AMap.Geolocation({ // 定位
enableHighAccuracy: true,
timeout: 10000,
zoomToAccuracy: true,
position: {
bottom: '20px',
right: '10px'
}
}));
// --- 初始化轿车规划 ---
driving = new AMap.Driving({
map: map,
panel: "panel", // 结果显示在 panel div 中
policy: AMap.DrivingPolicy.LEAST_TIME
});
// --- 初始化货车规划 (按需开启) ---
// 货车需要设置 size (1:微型, 2:轻型, 3:中型, 4:重型)
if(AMap.TruckDriving) {
truckDriving = new AMap.TruckDriving({
// --- 初始化轿车规划 ---
driving = new AMap.Driving({
map: map,
panel: "panel",
size: 2,
policy: 0, // 0: 躲避拥堵
width: 2.5,
height: 2,
load: 1,
weight: 10,
axlesNum: 2,
policy: AMap.DrivingPolicy.LEAST_TIME
});
// --- 初始化货车规划 ---
if (AMap.TruckDriving) {
truckDriving = new AMap.TruckDriving({
map: map,
panel: "panel",
size: 2,
policy: 0,
width: 2.5,
height: 2,
load: 1,
weight: 10,
axlesNum: 2,
});
}
// --- 输入提示 ---
new AMap.AutoComplete({
input: "endInput"
});
}
// --- 输入提示 (自动补全) ---
new AMap.AutoComplete({ input: "startInput" });
new AMap.AutoComplete({ input: "endInput" });
}
/**
* 核心功能 1: 接收 Flutter 传来的定位数据
* Flutter 端调用: webViewController.evaluateJavascript("updateMyLocation(...)")
*/
function updateMyLocation(lat, lng, angle) {
// 1. 更新全局变量,供 backToLocation 使用
currentLat = lat;
currentLng = lng;
// --- 被动接收 Flutter 传来的定位 ---
function updateMyLocation(lat, lng, angle) {
currentLat = lat;
currentLng = lng;
var position = [lng, lat];
var position = [lng, lat];
if (!marker) {
marker = new AMap.Marker({
map: map,
position: position,
icon: "https://webapi.amap.com/images/car.png",
offset: new AMap.Pixel(-26, -13),
autoRotation: true,
angle: angle || 0,
});
// 第一次定位移动中心
map.setCenter(position);
} else {
marker.setPosition(position);
if (angle) marker.setAngle(angle);
}
}
// 2. 绘制或移动 Marker (这就是所谓的“原有逻辑”)
if (!marker) {
// 如果是第一次收到定位,创建 Marker
marker = new AMap.Marker({
map: map,
position: position,
icon: "https://webapi.amap.com/images/car.png",
offset: new AMap.Pixel(-26, -13),
autoRotation: true,
angle: angle || 0,
});
map.setCenter(position); // 首次定位自动居中
// --- 核心:规划路线 ---
function startRouteSearch() {
var startKw = document.getElementById('startInput').value;
var endKw = document.getElementById('endInput').value;
if(!endKw) {
console.log("FlutterLog: 终点不能为空");
return;
// 自动填充起点输入框
document.getElementById('startInput').value = "我的位置";
} else {
// 后续定位,使用动画平滑移动
marker.moveTo(position, {
duration: 1000, // 假设 Flutter 每 1s 传一次数据
autoRotation: true
});
}
}
console.log("FlutterLog: 开始规划..." + (isTruckMode ? "货车" : "轿车"));
// 清除之前的路线
if(driving) driving.clear();
if(truckDriving) truckDriving.clear();
// 构造起点和终点参数
// 高德API Search方法支持点对象数组[{keyword: '名字', city: '城市'}, {keyword: '...'}]
var points = [];
// 1. 处理起点
if (startKw) {
// 如果用户输入了文字
points.push({ keyword: startKw });
} else {
// 如果用户没输入,使用当前定位
/**
* 核心功能 2: 点击按钮回到当前位置
*/
function backToLocation() {
if (currentLng && currentLat) {
map.panTo([currentLng, currentLat]);
map.setZoom(17);
console.log("JS: 已回到当前位置");
} else {
console.log("JS: 暂无定位数据,向 Flutter 请求...");
if (window.flutter_inappwebview) {
window.flutter_inappwebview.callHandler('requestLocation');
}
}
}
/**
* 核心功能 3: 路径规划
*/
function startRouteSearch() {
var endKw = document.getElementById('endInput').value;
if (!endKw) {
console.log("JS: 终点不能为空");
return;
}
// 清除旧路线
if (driving) driving.clear();
if (truckDriving) truckDriving.clear();
// 收起键盘
document.getElementById('endInput').blur();
// 构造参数
var points = [];
// 起点:默认使用当前定位
if (currentLng && currentLat) {
// 关键点:当混合使用坐标和关键字时,必须构建 LngLat 对象
points.push({
keyword: '我的位置',
location: new AMap.LngLat(currentLng, currentLat)
});
} else {
console.log("FlutterLog: 无定位数据且无输入");
alert("未获取到定位,请输入起点");
alert("未获取到定位,请稍后再试");
return;
}
// 终点
points.push({
keyword: endKw
});
// 开始搜索 (以轿车为例)
driving.search(points, function (status, result) {
if (status === 'complete') {
console.log('JS: 规划成功');
// --- 成功后的 UI 联动 (这就是“原有逻辑”中负责界面的部分) ---
var panel = document.getElementById('panel');
panel.style.display = 'block';
// 给 body 加类名,让定位按钮上移
document.body.classList.add('panel-active');
} else {
console.log('JS: 规划失败: ' + result);
alert("规划失败,请检查地点名称");
}
});
}
// 2. 处理终点
points.push({ keyword: endKw });
// 显示底部面板
document.getElementById('panel').style.display = 'block';
// 3. 发起请求
if (isTruckMode && truckDriving) {
// 货车接口略有不同,需要传入 path 数组
// truckDriving.search(path, callback)
// 这里为了简化,我们先演示轿车。货车通常需要具体的经纬度,建议先通过 Geocoder 把 endKw 转成经纬度再传给货车接口
console.log("FlutterLog: 货车API需要更严格的经纬度参数建议先使用轿车演示");
// 辅助功能:手动绘制路线 (Flutter 可能用到)
function drawCustomRoute(pointsJsonString) {
var path = typeof pointsJsonString === 'string' ? JSON.parse(pointsJsonString) : pointsJsonString;
if (driving) driving.clear();
var polyline = new AMap.Polyline({
path: path,
isOutline: true,
outlineColor: '#ffeeee',
borderWeight: 3,
strokeColor: "#3366FF",
strokeWeight: 6,
lineJoin: 'round'
});
map.add(polyline);
map.setFitView([polyline]);
}
// 默认使用轿车规划 (支持 keyword + location 混合)
driving.search(points, function(status, result) {
if (status === 'complete') {
console.log('FlutterLog: 规划成功');
} else {
console.log('FlutterLog: 规划失败: ' + result);
// 常见错误: "USER_DAILY_QUERY_OVER_LIMIT" (Key额度超限)
// "INVALID_USER_KEY" (Key错误)
// "no_data" (地点没找到)
}
});
}
// --- 绘制自定义路径 (保持原有功能) ---
function drawCustomRoute(pointsJsonString) {
// 如果是从Flutter传来的JSON字符串需要Parse如果是对象则直接用
var path = typeof pointsJsonString === 'string' ? JSON.parse(pointsJsonString) : pointsJsonString;
if (driving) driving.clear();
var polyline = new AMap.Polyline({
path: path,
isOutline: true,
outlineColor: '#ffeeee',
borderWeight: 3,
strokeColor: "#3366FF",
strokeWeight: 6,
lineJoin: 'round'
});
map.add(polyline);
map.setFitView([polyline]);
}
window.onload = initMap;
</script>
window.onload = initMap;
</script>
</body>
</html>