feat(map): 滚轮缩放以光标为焦点并调整保存文案

This commit is contained in:
2026-08-12 11:15:25 +08:00
parent 03d319ebf6
commit 0915529af0

View File

@@ -557,7 +557,7 @@ function markCurrentMapUploaded(payload: Partial<MapRecord>) {
currentConfig.value.lastSyncedAt = nowString(); currentConfig.value.lastSyncedAt = nowString();
} }
// 调用小车地图地址接口,在保存下发时单独保存 PGM 和 YAML 文件 URL // 调用小车地图地址接口,在保存时单独保存 PGM 和 YAML 文件 URL
async function saveCurrentMapUrls() { async function saveCurrentMapUrls() {
if (!currentConfiguredDevice.value || !currentConfig.value) { if (!currentConfiguredDevice.value || !currentConfig.value) {
return; return;
@@ -717,7 +717,7 @@ async function handleMapImageFileChange(event: Event) {
rosMapMeta.imageUrl = uploadedUrl; rosMapMeta.imageUrl = uploadedUrl;
markCurrentMapUploaded({ imageUrl: uploadedUrl, name: file.name }); markCurrentMapUploaded({ imageUrl: uploadedUrl, name: file.name });
mapUploadMessage.value = "地图 PGM 上传成功,保存下发后生效"; mapUploadMessage.value = "地图 PGM 上传成功,保存后生效";
} catch (error) { } catch (error) {
console.error(error); console.error(error);
mapUploadMessage.value = "地图 PGM 解析或上传失败,请确认文件为 P5 格式"; mapUploadMessage.value = "地图 PGM 解析或上传失败,请确认文件为 P5 格式";
@@ -769,7 +769,7 @@ async function handleMapConfigFileChange(event: Event) {
rosMapMeta.configUrl = uploadedUrl; rosMapMeta.configUrl = uploadedUrl;
markCurrentMapUploaded({ configUrl: uploadedUrl }); markCurrentMapUploaded({ configUrl: uploadedUrl });
mapUploadMessage.value = "地图配置上传成功,保存下发后生效"; mapUploadMessage.value = "地图配置上传成功,保存后生效";
scheduleMapCanvasRender(); scheduleMapCanvasRender();
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@@ -1507,9 +1507,26 @@ function clampMapZoom(value: number) {
return Math.min(maxMapZoom, Math.max(minMapZoom, Number(value.toFixed(2)))); return Math.min(maxMapZoom, Math.max(minMapZoom, Number(value.toFixed(2))));
} }
// 设置地图缩放比例并触发画布重绘 // 设置地图缩放比例并触发画布重绘;传入 focusPoint画布内坐标时缩放保持该焦点下的地图点不动
function setMapZoom(value: number) { function setMapZoom(value: number, focusPoint?: { x: number; y: number }) {
mapZoom.value = clampMapZoom(value); const nextZoom = clampMapZoom(value);
if (focusPoint && nextZoom !== mapZoom.value) {
const rect = getMapStageRect();
if (rect && rect.width > 0 && rect.height > 0) {
const frame = getRosMapFrame(rect);
const pointerRatioX = (focusPoint.x - frame.left) / frame.width;
const pointerRatioY = (focusPoint.y - frame.top) / frame.height;
const nextWidth = frame.width * (nextZoom / mapZoom.value);
const nextHeight = frame.height * (nextZoom / mapZoom.value);
mapPan.x += (frame.width - nextWidth) * (pointerRatioX - 0.5);
mapPan.y += (frame.height - nextHeight) * (pointerRatioY - 0.5);
}
}
mapZoom.value = nextZoom;
scheduleMapCanvasRender(); scheduleMapCanvasRender();
} }
@@ -1531,10 +1548,12 @@ function resetMapView() {
focusMapOnOrigin(); focusMapOnOrigin();
} }
// 处理鼠标滚轮缩放地图 // 处理鼠标滚轮缩放地图,以光标位置为缩放中心
function handleMapWheel(event: WheelEvent) { function handleMapWheel(event: WheelEvent) {
const rect = getMapStageRect();
const zoomFactor = event.deltaY > 0 ? 1 / 1.1 : 1.1; const zoomFactor = event.deltaY > 0 ? 1 / 1.1 : 1.1;
setMapZoom(mapZoom.value * zoomFactor); const focusPoint = rect ? { x: event.clientX - rect.left, y: event.clientY - rect.top } : undefined;
setMapZoom(mapZoom.value * zoomFactor, focusPoint);
} }
// 根据地图宽高比计算默认缩放:常规比例地图保持完整显示,宽扁/高瘦地图放大让短边占满画布 // 根据地图宽高比计算默认缩放:常规比例地图保持完整显示,宽扁/高瘦地图放大让短边占满画布
@@ -2820,7 +2839,7 @@ watch(
</button> </button>
<button class="page-action-btn primary" :disabled="saveProgressVisible" type="button" <button class="page-action-btn primary" :disabled="saveProgressVisible" type="button"
@click="saveConfigDialog"> @click="saveConfigDialog">
{{ saveProgressVisible ? "保存中..." : "保存下发" }} {{ saveProgressVisible ? "保存中..." : "保存" }}
</button> </button>
</div> </div>
</div> </div>
@@ -3047,7 +3066,7 @@ watch(
<div v-if="saveProgressVisible" class="save-progress-mask"> <div v-if="saveProgressVisible" class="save-progress-mask">
<div class="save-progress-card"> <div class="save-progress-card">
<div class="save-progress-title">保存下发</div> <div class="save-progress-title">保存</div>
<div class="save-progress-text">{{ saveProgressMessage }}</div> <div class="save-progress-text">{{ saveProgressMessage }}</div>
<div class="save-progress-track"> <div class="save-progress-track">
<div class="save-progress-fill" :style="{ width: `${saveProgressValue}%` }"></div> <div class="save-progress-fill" :style="{ width: `${saveProgressValue}%` }"></div>