From 1bc33546a044cbc84dd9595c19dbcd9a4e309fc9 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期六, 10 一月 2026 14:06:10 +0800
Subject: [PATCH] #
---
zy-acs-flow/src/map/tool.js | 206 +++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 174 insertions(+), 32 deletions(-)
diff --git a/zy-acs-flow/src/map/tool.js b/zy-acs-flow/src/map/tool.js
index 8966bf2..abc1b4f 100644
--- a/zy-acs-flow/src/map/tool.js
+++ b/zy-acs-flow/src/map/tool.js
@@ -29,6 +29,13 @@
import ctuLoadedNoBattery from '/map/agv/ctuLoadedNoBattery.svg';
import ctuLoadedHalfBattery from '/map/agv/ctuLoadedHalfBattery.svg';
import ctuLoadedFullBattery from '/map/agv/ctuLoadedFullBattery.svg';
+// asr
+import ASREmptyNoBattery from '/map/asr/ASREmptyNoBattery.svg';
+import ASREmptyHalfBattery from '/map/asr/ASREmptyHalfBattery.svg';
+import ASREmptyFullBattery from '/map/asr/ASREmptyFullBattery.svg';
+import ASRLoadedNoBattery from '/map/asr/ASRLoadedNoBattery.svg';
+import ASRLoadedHalfBattery from '/map/asr/ASRLoadedHalfBattery.svg';
+import ASRLoadedFullBattery from '/map/asr/ASRLoadedFullBattery.svg';
let app, mapContainer, themeMode;
let selectedSprite, effectOverlay, effectTicker;
@@ -78,7 +85,7 @@
return { mapX: mapPoint.x, mapY: mapPoint.y };
}
-export const generateSprite = (deviceType, texture) => {
+export const generateSprite = (deviceType, texture, agvModel) => {
let sprite;
switch (deviceType) {
case DEVICE_TYPE.SHELF:
@@ -111,9 +118,14 @@
if (texture) {
sprite = new PIXI.Sprite(PIXI.Texture.from(texture, { resourceOptions: { scale: 1 } }));
}
- sprite.width = 750;
- sprite.height = 1300;
sprite.zIndex = DEVICE_Z_INDEX.AGV;
+
+ if (agvModel === 'HEAVY_LOAD_STACKING_ROBOT') {
+ sprite.scale.set(13, 11);
+ } else {
+ sprite.width = 750;
+ sprite.height = 1300;
+ }
break
case DEVICE_TYPE.POINT:
sprite = new PIXI.Sprite(PIXI.Texture.from(point, { resourceOptions: { scale: 1 } }));
@@ -399,6 +411,20 @@
.start();
}
+export const findAreaSpriteById = (areaId) => {
+ if (!mapContainer || areaId == null) {
+ return null;
+ }
+ const targetId = String(areaId);
+ for (let i = 0; i < mapContainer.children.length; i += 1) {
+ const child = mapContainer.children[i];
+ if (child?.data?.type === DEVICE_TYPE.AREA && String(child.data?.id) === targetId) {
+ return child;
+ }
+ }
+ return null;
+};
+
export const clearMapData = () => {
if (!mapContainer) {
return;
@@ -583,6 +609,12 @@
if (!mapContainer || !sprite) {
return;
}
+ const data = sprite.data || (sprite.data = {});
+
+ if (data.rotationTween) {
+ data.rotationTween.stop();
+ data.rotationTween = null;
+ }
// origin
let currentRotation = sprite.rotation + rotationOffset;
// target
@@ -598,7 +630,7 @@
// destination
const endRotation = sprite.rotation + rotationDifference;
- new TWEEDLE.Tween(sprite)
+ const rotationTween = new TWEEDLE.Tween(sprite)
.to({ rotation: endRotation }, ANIMATE_DURING_TIME)
.easing(TWEEDLE.Easing.Linear.None)
.onUpdate(() => {
@@ -608,6 +640,12 @@
}
})
.start();
+ data.rotationTween = rotationTween;
+ rotationTween.onComplete(() => {
+ if (data.rotationTween === rotationTween) {
+ data.rotationTween = null;
+ }
+ });
};
export const incrementSpriteNo = (str, incrementValue) => {
@@ -661,22 +699,45 @@
}
}
-export const generateAgvSpriteTexture = (agvStatusMode) => {
- switch (agvStatusMode) {
- case AGV_STATUS_MODE.EMPTY_NO_BATTERY:
- return ctuEmptyNoBattery;
- case AGV_STATUS_MODE.EMPTY_HALF_BATTERY:
- return ctuEmptyHalfBattery;
- case AGV_STATUS_MODE.EMPTY_FULL_BATTERY:
- return ctuEmptyFullBattery;
- case AGV_STATUS_MODE.LOADED_NO_BATTERY:
- return ctuLoadedNoBattery;
- case AGV_STATUS_MODE.LOADED_HALF_BATTERY:
- return ctuLoadedHalfBattery;
- case AGV_STATUS_MODE.LOADED_FULL_BATTERY:
- return ctuLoadedFullBattery;
- default:
- return;
+export const generateAgvSpriteTexture = (agvModel, agvStatusMode) => {
+ if (!agvModel) {
+ console.error("failed to load agv model");
+ return;
+ }
+ if (agvModel === 'HEAVY_LOAD_STACKING_ROBOT') {
+ switch (agvStatusMode) {
+ case AGV_STATUS_MODE.EMPTY_NO_BATTERY:
+ return ASREmptyNoBattery;
+ case AGV_STATUS_MODE.EMPTY_HALF_BATTERY:
+ return ASREmptyHalfBattery;
+ case AGV_STATUS_MODE.EMPTY_FULL_BATTERY:
+ return ASREmptyFullBattery;
+ case AGV_STATUS_MODE.LOADED_NO_BATTERY:
+ return ASRLoadedNoBattery;
+ case AGV_STATUS_MODE.LOADED_HALF_BATTERY:
+ return ASRLoadedHalfBattery;
+ case AGV_STATUS_MODE.LOADED_FULL_BATTERY:
+ return ASRLoadedFullBattery;
+ default:
+ return;
+ }
+ } else {
+ switch (agvStatusMode) {
+ case AGV_STATUS_MODE.EMPTY_NO_BATTERY:
+ return ctuEmptyNoBattery;
+ case AGV_STATUS_MODE.EMPTY_HALF_BATTERY:
+ return ctuEmptyHalfBattery;
+ case AGV_STATUS_MODE.EMPTY_FULL_BATTERY:
+ return ctuEmptyFullBattery;
+ case AGV_STATUS_MODE.LOADED_NO_BATTERY:
+ return ctuLoadedNoBattery;
+ case AGV_STATUS_MODE.LOADED_HALF_BATTERY:
+ return ctuLoadedHalfBattery;
+ case AGV_STATUS_MODE.LOADED_FULL_BATTERY:
+ return ctuLoadedFullBattery;
+ default:
+ return;
+ }
}
}
@@ -743,7 +804,7 @@
const agvRotationOffset = rotationParseNum(AGV_ANGLE_OFFSET_VAL);
const showAgvSprite = (curZone, agvVo, setCurSprite) => {
- const { agvNo, code, direction, battery, jobType, backpack: backpackCount, slots, error } = agvVo;
+ const { agvNo, agvModel, code, direction, battery, jobType, backpack: backpackCount, slots, error } = agvVo;
if (!code) { return; }
const codeSprite = querySprite(DEVICE_TYPE.POINT, code);
if (!codeSprite) { return; }
@@ -754,12 +815,13 @@
let agvSprite = querySprite(DEVICE_TYPE.AGV, agvNo);
if (!agvSprite) {
const agvStatusMode = getAgvStatusMode(backpackCount, battery);
- const agvTexture = generateAgvSpriteTexture(agvStatusMode);
- agvSprite = generateSprite(DEVICE_TYPE.AGV, agvTexture);
+ const agvTexture = generateAgvSpriteTexture(agvModel, agvStatusMode);
+ agvSprite = generateSprite(DEVICE_TYPE.AGV, agvTexture, agvModel);
initSprite(agvSprite, DEVICE_TYPE.AGV);
agvSprite.data.no = agvNo;
+ agvSprite.data.model = agvModel;
agvSprite.data.backpackCount = backpackCount;
agvSprite.data.battery = battery;
@@ -774,12 +836,16 @@
});
agvText.anchor.set(0.5, 0.5);
agvText.position.set(0, 8);
+ if (agvModel === 'HEAVY_LOAD_STACKING_ROBOT') {
+ agvText.position.set(0, 20);
+ }
agvText.scale.set(MAP_MIRROR ? -1 : 1, 1)
agvSprite.addChild(agvText);
agvSprite.updateTextRotation = () => {
if (agvText && agvSprite) {
agvText.rotation = -agvSprite.rotation - rotationParseNum(MAP_DEFAULT_ROTATION);
+ // agvText.rotation = -agvSprite.rotation - rotationParseNum(MAP_DEFAULT_ROTATION + 180);
}
};
agvSprite.updateTextRotation();
@@ -829,13 +895,24 @@
beInsight(agvSprite, setCurSprite);
- new TWEEDLE.Tween(agvSprite.position)
+ if (agvSprite.data.moveTween) {
+ agvSprite.data.moveTween.stop();
+ agvSprite.data.moveTween = null;
+ }
+
+ const moveTween = new TWEEDLE.Tween(agvSprite.position)
.to({
x: codeSprite.position.x,
y: codeSprite.position.y
}, ANIMATE_DURING_TIME)
.easing(TWEEDLE.Easing.Linear.None)
.start();
+ agvSprite.data.moveTween = moveTween;
+ moveTween.onComplete(() => {
+ if (agvSprite.data?.moveTween === moveTween) {
+ agvSprite.data.moveTween = null;
+ }
+ });
}
const drawerAgvPath = (curZone, agvVo) => {
@@ -886,6 +963,14 @@
for (let i = mapContainer.children.length - 1; i >= 0; i--) {
const child = mapContainer.children[i];
if (child?.data?.type === DEVICE_TYPE.AGV) {
+ if (child.data.moveTween) {
+ child.data.moveTween.stop();
+ child.data.moveTween = null;
+ }
+ if (child.data.rotationTween) {
+ child.data.rotationTween.stop();
+ child.data.rotationTween = null;
+ }
if (child.data.jobEffect) {
app?.ticker.remove(child.data.jobEffect._onTick);
child.removeChild(child.data.jobEffect);
@@ -911,14 +996,25 @@
const addAreaLabel = (draft, text, from, to) => {
const centerX = (from.x + to.x) / 2;
const centerY = (from.y + to.y) / 2;
- const label = new PIXI.Text(text, {
- fill: themeMode === 'dark' ? '#f1f2f6' : '#535353ff',
- fontSize: 20 / Math.abs(mapContainer.scale.x || 1),
- fontWeight: 'bold',
+ const currentScale = Math.abs(mapContainer.scale.x || 1);
+ const labelStyle = new PIXI.TextStyle({
+ fontFamily: 'Inter, "Segoe UI", sans-serif',
+ fill: themeMode === 'dark' ? '#f1f2f6' : '#606060ff',
+ fontSize: Math.max(16, 20 / currentScale),
+ fontWeight: 600,
+ letterSpacing: 10,
+ // stroke: themeMode === 'dark' ? '#1e272e' : '#ffffff',
+ // strokeThickness: Math.max(1, 2 / currentScale),
+ // dropShadow: true,
+ // dropShadowColor: themeMode === 'dark' ? '#00000066' : '#95a5a6',
+ // dropShadowBlur: 1.5,
+ // dropShadowAngle: Math.PI / 4,
+ // dropShadowDistance: 2,
});
+ const label = new PIXI.Text(text ?? '', labelStyle);
label.anchor.set(0.5);
label.position.set(centerX, centerY);
- label.rotation = rotationParseNum(MAP_DEFAULT_ROTATION);
+ label.rotation = -rotationParseNum(MAP_DEFAULT_ROTATION);
label.scale.set(MAP_MIRROR ? -1 : 1, 1);
draft.addChild(label);
};
@@ -988,9 +1084,9 @@
draft.name = id ? `area_${id}` : 'area_' + generateID();
draft.zIndex = 0;
if (setCurSprite) {
- draft.lineStyle(2 / Math.abs(mapContainer.scale.x || 1), AREA_BORDER_COLOR, 0.9);
draft.zIndex = DEVICE_Z_INDEX.AREA;
}
+ draft.lineStyle(1 / Math.abs(mapContainer.scale.x || 1), AREA_BORDER_COLOR, 0.9);
draft.beginFill(areaColor, 0.18);
draft.drawRect(
Math.min(from.x, to.x),
@@ -1001,8 +1097,10 @@
draft.endFill();
addAreaLabel(draft, name, from, to);
draft.data = { ...(draft.data || {}), type: DEVICE_TYPE.AREA, name, color: areaColor, id, start: from, end: to };
- draft.eventMode = 'static';
- draft.cursor = 'pointer';
+ if (setCurSprite) {
+ draft.cursor = 'pointer';
+ draft.eventMode = 'static';
+ }
if (setCurSprite) {
draft.off('click');
draft.on('click', () => setCurSprite(draft));
@@ -1133,3 +1231,47 @@
clearAreas();
setShowAreas(false);
};
+
+export const focusAreaSprite = (sprite, rightPanelWidth) => {
+ if (!sprite || !app || !mapContainer) {
+ return;
+ }
+
+ const data = sprite.data || {};
+ const start = data.start;
+ const end = data.end;
+ const currentScale = Math.abs(mapContainer.scale.x || 1);
+ const boundsBefore = sprite.getBounds();
+ const width = start && end ? Math.abs(end.x - start.x) : boundsBefore.width / currentScale;
+ const height = start && end ? Math.abs(end.y - start.y) : boundsBefore.height / currentScale;
+
+ const paddedWidth = (width || 1000) * 1.25;
+ const paddedHeight = (height || 1000) * 1.25;
+ const viewportWidth = app.renderer.width || 1920;
+ const viewportHeight = app.renderer.height || 1080;
+ const effectiveViewportWidth = Math.max(1, viewportWidth - rightPanelWidth);
+
+ let focusScale = Math.min(
+ (effectiveViewportWidth * 0.65) / paddedWidth,
+ (viewportHeight * 0.65) / paddedHeight
+ );
+ focusScale = Math.min(Math.max(focusScale, 0.03), 0.25);
+
+ mapContainer.scale.set(MAP_MIRROR ? -focusScale : focusScale, focusScale);
+ mapContainer.position.set(0, 0);
+
+ const bounds = sprite.getBounds();
+ const centerX = bounds.x + bounds.width / 2;
+ const centerY = bounds.y + bounds.height / 2;
+ const visibleCenterX = (viewportWidth - rightPanelWidth) / 2;
+
+ const targetPos = {
+ x: visibleCenterX - centerX,
+ y: viewportHeight / 2 - centerY,
+ };
+
+ new TWEEDLE.Tween(mapContainer.position)
+ .easing(TWEEDLE.Easing.Quadratic.Out)
+ .to(targetPos, 500)
+ .start();
+};
--
Gitblit v1.9.1