From b289a4c397c65f40aa89d13604a51f9f13a0328f Mon Sep 17 00:00:00 2001 From: luxiaotao1123 <t1341870251@163.com> Date: 星期六, 19 十月 2024 10:17:50 +0800 Subject: [PATCH] # --- zy-acs-flow/src/map/tool.js | 418 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 327 insertions(+), 91 deletions(-) diff --git a/zy-acs-flow/src/map/tool.js b/zy-acs-flow/src/map/tool.js index 3abcf46..8f942a9 100644 --- a/zy-acs-flow/src/map/tool.js +++ b/zy-acs-flow/src/map/tool.js @@ -3,6 +3,7 @@ import { DEVICE_TYPE, DEVICE_Z_INDEX, + AGV_STATUS_MODE, } from './constants'; import shelf from '/map/shelf.svg'; @@ -10,6 +11,13 @@ import station from '/map/station.svg'; import direction from '/map/direction.svg'; import point from '/map/point.svg'; +// agv +import ctuEmptyNoBattery from '/map/agv/ctuEmptyNoBattery.svg'; +import ctuEmptyHalfBattery from '/map/agv/ctuEmptyHalfBattery.svg'; +import ctuEmptyFullBattery from '/map/agv/ctuEmptyFullBattery.svg'; +import ctuLoadedNoBattery from '/map/agv/ctuLoadedNoBattery.svg'; +import ctuLoadedHalfBattery from '/map/agv/ctuLoadedHalfBattery.svg'; +import ctuLoadedFullBattery from '/map/agv/ctuLoadedFullBattery.svg'; let app, mapContainer, themeMode; let selectedSprite, effectTick, effectHalfCircle, effectRectangle; @@ -47,7 +55,7 @@ } } -export const generateSprite = (deviceType) => { +export const generateSprite = (deviceType, source) => { let sprite; switch (deviceType) { case DEVICE_TYPE.SHELF: @@ -74,6 +82,16 @@ // sprite.height = 63; sprite.zIndex = DEVICE_Z_INDEX.DIRECTION; break; + + + case DEVICE_TYPE.AGV: + if (source) { + sprite = new PIXI.Sprite(PIXI.Texture.from(source, { resourceOptions: { scale: 1 } })); + } + sprite.width = 300; + sprite.height = 500; + sprite.zIndex = DEVICE_Z_INDEX.AGV; + break case DEVICE_TYPE.POINT: sprite = new PIXI.Sprite(PIXI.Texture.from(point, { resourceOptions: { scale: 1 } })); // sprite.width = 112; @@ -83,7 +101,7 @@ default: break; } - if (sprite) { + if (sprite && deviceType !== DEVICE_TYPE.AGV) { sprite.blendMode = PIXI.BLEND_MODES.MULTIPLY; } return sprite; @@ -100,49 +118,27 @@ }; } +export const querySprite = (type, no) => { + if (!mapContainer) { + return; + } + for (const sprite of mapContainer.children) { + if (sprite.data?.type === type && sprite.data?.no === no) { + return sprite; + } + } +} + +export const findSpriteByUuid = (uuid) => { + return mapContainer?.children?.find(child => child?.data?.uuid === uuid); +} + export const markSprite = (sprite) => { sprite.alpha = 0.5; } export const unMarkSprite = (sprite) => { sprite.alpha = 1; -} - -export const beMovable = (sprite) => { - sprite.off('pointerup'); - sprite.off('pointermove'); - sprite.off('pointerdown'); - sprite.off('click'); - - sprite.on("pointerdown", onDragStart); - - let dragTarget; - function onDragStart(event) { - if (event.button === 0) { - dragTarget = event.currentTarget; - mapContainer.parent.off('pointermove'); - mapContainer.parent.on('pointermove', onDragMove, dragTarget); - - mapContainer.parent.off('pointerup'); - mapContainer.parent.on('pointerup', onDragEnd.bind(mapContainer)); - } - } - - function onDragMove(event) { - if (this) { - this.parent.toLocal(event.global, null, this.position); - } - } - - function onDragEnd() { - if (dragTarget) { - this.parent.off('pointermove'); - this.parent.off('pointerup'); - dragTarget.alpha = 1; - dragTarget = null; - } - } - } export const spriteListBeMovable = (selectedSprites, endFn) => { @@ -221,6 +217,57 @@ && spriteBounds.y < boxBounds.y + boxBounds.height; } +export const beInsight = (sprite, setCurSprite) => { + sprite.off('pointerup'); + sprite.off('pointermove'); + sprite.off('pointerdown'); + sprite.off('click'); + + sprite.on("click", onClick); + + function onClick(event) { + setCurSprite(sprite); + } + +} + +export const beMovable = (sprite) => { + sprite.off('pointerup'); + sprite.off('pointermove'); + sprite.off('pointerdown'); + sprite.off('click'); + + sprite.on("pointerdown", onDragStart); + + let dragTarget; + function onDragStart(event) { + if (event.button === 0) { + dragTarget = event.currentTarget; + mapContainer.parent.off('pointermove'); + mapContainer.parent.on('pointermove', onDragMove, dragTarget); + + mapContainer.parent.off('pointerup'); + mapContainer.parent.on('pointerup', onDragEnd.bind(mapContainer)); + } + } + + function onDragMove(event) { + if (this) { + this.parent.toLocal(event.global, null, this.position); + } + } + + function onDragEnd() { + if (dragTarget) { + this.parent.off('pointermove'); + this.parent.off('pointerup'); + dragTarget.alpha = 1; + dragTarget = null; + } + } + +} + export const beSettings = (sprite, setSpriteSettings) => { sprite.off('pointerup'); sprite.off('pointermove'); @@ -232,6 +279,33 @@ function onClick(event) { setSpriteSettings(sprite); } +} + +export const focusSprite = (sprite) => { + if (!sprite || !app || !mapContainer) { + return; + } + + mapContainer.scale.set(0.3); + mapContainer.position.set(0, 0); + + let bounds = sprite.getBounds(); + let focusPoint = { + x: bounds.x + bounds.width / 2, + y: bounds.y + bounds.height / 2 + }; + + let targetPos = { + x: app.renderer.width / 4 - focusPoint.x, + y: app.renderer.height / 2 - focusPoint.y + }; + + new TWEEDLE.Tween(mapContainer.position) + .easing(TWEEDLE.Easing.Quadratic.Out) + .to(targetPos, 500) + .onComplete(() => { + }) + .start(); } export const clearMapData = () => { @@ -256,82 +330,170 @@ } } + +// export const showSelectedEffect = (sprite) => { +// if (!sprite?.texture || !sprite?.texture?.valid) { +// return; +// } +// const { width, height } = sprite; +// const scale = sprite.scale.x; +// const sideLen = (Math.max(width, height) + 10) * scale; +// const color = themeMode === 'light' ? 0x273c75 : 0xffffff; + +// effectHalfCircle = new PIXI.Graphics(); +// effectHalfCircle.beginFill(color); +// effectHalfCircle.lineStyle(2 * scale, color); +// effectHalfCircle.arc(0, 0, sideLen, 0, Math.PI); +// effectHalfCircle.endFill(); +// effectHalfCircle.position.set(sprite.x, sprite.y); +// effectHalfCircle.scale.set(1 / scale); +// effectHalfCircle.zIndex = 9999; + +// effectRectangle = new PIXI.Graphics(); +// effectRectangle.lineStyle(5 * scale, color, 1); +// effectRectangle.drawRoundedRect(0, 0, sideLen, sideLen, 16 * scale); +// effectRectangle.endFill(); +// effectRectangle.mask = effectHalfCircle; +// effectRectangle.zIndex = 9999; + +// const scaledWidth = sideLen * (1 / scale); +// const scaledHeight = sideLen * (1 / scale); + +// effectRectangle.scale.set(1 / scale); +// effectRectangle.position.set(sprite.x - scaledWidth / 2, sprite.y - scaledHeight / 2); + +// mapContainer.addChild(effectRectangle); +// mapContainer.addChild(effectHalfCircle); + +// selectedSprite = sprite; + +// let phase = 0; +// effectTick = (delta) => { +// phase += delta / 10; +// phase %= (Math.PI * 2); +// if (effectHalfCircle) { +// effectHalfCircle.rotation = phase; +// } +// }; + +// app.ticker.add(effectTick); +// } + +// export const removeSelectedEffect = () => { +// if (effectTick) { +// app.ticker.remove(effectTick); +// } +// if (effectHalfCircle) { +// mapContainer.removeChild(effectHalfCircle); +// effectHalfCircle = null; +// } +// if (effectRectangle) { +// mapContainer.removeChild(effectRectangle); +// effectRectangle = null; +// } +// selectedSprite = null; +// } + +// export const updateEffect = (sprite) => { +// if (!sprite || sprite !== selectedSprite || !effectRectangle || !effectHalfCircle) { +// return +// } +// const { width, height } = sprite; +// const scale = sprite?.scale.x; +// const sideLen = (Math.max(width, height) + 10) * scale; +// const scaledWidth = sideLen * (1 / scale); +// const scaledHeight = sideLen * (1 / scale); + +// effectRectangle.position.set(sprite.x - scaledWidth / 2, sprite.y - scaledHeight / 2); + +// effectHalfCircle.position.set(sprite.x, sprite.y); +// } + +let effectCircle = null; +let effectTicker = null; + export const showSelectedEffect = (sprite) => { if (!sprite?.texture || !sprite?.texture?.valid) { return; } + + // 濡傛灉宸茬粡鏈夌壒鏁堬紝鍏堢Щ闄� + removeSelectedEffect(); + const { width, height } = sprite; const scale = sprite.scale.x; - const sideLen = (Math.max(width, height) + 10) * scale; + const maxDimension = Math.max(width, height); + const radius = (maxDimension / 2) * scale * 1.2; // 鏀惧ぇ1.2鍊嶏紝浣垮渾绋嶅ぇ浜巗prite + const color = themeMode === 'light' ? 0x273c75 : 0xffffff; - effectHalfCircle = new PIXI.Graphics(); - effectHalfCircle.beginFill(color); - effectHalfCircle.lineStyle(2 * scale, color); - effectHalfCircle.arc(0, 0, sideLen, 0, Math.PI); - effectHalfCircle.endFill(); - effectHalfCircle.position.set(sprite.x, sprite.y); - effectHalfCircle.scale.set(1 / scale); - effectHalfCircle.zIndex = 9999; + // 鍒涘缓鍦嗗舰鐗规晥 + effectCircle = new PIXI.Graphics(); + effectCircle.lineStyle(2 * scale, color, 1); + effectCircle.drawCircle(0, 0, radius); + effectCircle.endFill(); + effectCircle.position.set(sprite.x, sprite.y); + effectCircle.zIndex = sprite.zIndex - 1; // 纭繚涓嶉伄鎸prite - effectRectangle = new PIXI.Graphics(); - effectRectangle.lineStyle(5 * scale, color, 1); - effectRectangle.drawRoundedRect(0, 0, sideLen, sideLen, 16 * scale); - effectRectangle.endFill(); - effectRectangle.mask = effectHalfCircle; - effectRectangle.zIndex = 9999; - - const scaledWidth = sideLen * (1 / scale); - const scaledHeight = sideLen * (1 / scale); - - effectRectangle.scale.set(1 / scale); - effectRectangle.position.set(sprite.x - scaledWidth / 2, sprite.y - scaledHeight / 2); - - mapContainer.addChild(effectRectangle); - mapContainer.addChild(effectHalfCircle); + // 灏嗙壒鏁堟坊鍔犲埌瀹瑰櫒涓� + mapContainer.addChild(effectCircle); selectedSprite = sprite; - let phase = 0; - effectTick = (delta) => { - phase += delta / 10; - phase %= (Math.PI * 2); - if (effectHalfCircle) { - effectHalfCircle.rotation = phase; + // 瀹炵幇鑴夊啿鏁堟灉 + let pulseScale = 1; + let scalingUp = true; + effectTicker = (delta) => { + const pulseSpeed = 0.005 * delta; + if (scalingUp) { + pulseScale += pulseSpeed; + if (pulseScale >= 1.2) { + scalingUp = false; + } + } else { + pulseScale -= pulseSpeed; + if (pulseScale <= 1) { + scalingUp = true; + } } + effectCircle.scale.set(pulseScale); + // 濮嬬粓璺熼殢sprite鐨勪綅缃� + effectCircle.position.set(selectedSprite.x, selectedSprite.y); }; - app.ticker.add(effectTick); -} + app.ticker.add(effectTicker); +}; export const removeSelectedEffect = () => { - if (effectTick) { - app.ticker.remove(effectTick); + if (effectTicker) { + app.ticker.remove(effectTicker); + effectTicker = null; } - if (effectHalfCircle) { - mapContainer.removeChild(effectHalfCircle); - effectHalfCircle = null; - } - if (effectRectangle) { - mapContainer.removeChild(effectRectangle); - effectRectangle = null; + if (effectCircle) { + mapContainer.removeChild(effectCircle); + effectCircle.destroy(); + effectCircle = null; } selectedSprite = null; -} +}; -export const updateEffect = (sprite) => { - if (!sprite || sprite !== selectedSprite || !effectRectangle || !effectHalfCircle) { - return +export const updateEffect = () => { + if (!selectedSprite || !effectCircle) { + return; } - const { width, height } = sprite; - const scale = sprite?.scale.x; - const sideLen = (Math.max(width, height) + 10) * scale; - const scaledWidth = sideLen * (1 / scale); - const scaledHeight = sideLen * (1 / scale); + // 鏇存柊鍦嗙殑浣嶇疆锛岀‘淇濊窡闅弒prite + effectCircle.position.set(selectedSprite.x, selectedSprite.y); +}; - effectRectangle.position.set(sprite.x - scaledWidth / 2, sprite.y - scaledHeight / 2); +export const multipleSelectEnhancer = (selectedSprites, setCurSprite, setBatchSprites) => { + selectedSprites = selectedSprites.filter(sprite => sprite.data?.type); - effectHalfCircle.position.set(sprite.x, sprite.y); + if (selectedSprites.length === 1) { + unMarkSprite(selectedSprites[0]); + setCurSprite(selectedSprites[0]); + } else { + setBatchSprites(selectedSprites); + } } export const rotationToNum = (rotation) => { @@ -375,4 +537,78 @@ parentElement.style.paddingLeft = param; parentElement.style.paddingRight = param; } +} + + +// service ------------------------ + +export const getAgvStatusMode = (backpack, battery) => { + if (backpack === 0) { + if (battery < 10) { + return AGV_STATUS_MODE.EMPTY_NO_BATTERY; + } + if (battery < 80) { + return AGV_STATUS_MODE.EMPTY_HALF_BATTERY; + } + return AGV_STATUS_MODE.EMPTY_FULL_BATTERY; + } else { + if (battery < 10) { + return AGV_STATUS_MODE.LOADED_NO_BATTERY; + } + if (battery < 80) { + return AGV_STATUS_MODE.LOADED_HALF_BATTERY; + } + return AGV_STATUS_MODE.LOADED_FULL_BATTERY; + } +} + +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; + } +} + + +// dynamic graphic ---------------- + +export const generateDynamicGraphic = (curZone, data, setCurSprite) => { + // console.log("ws", curZone, data); + + for (const agv of data.agvVos) { + showAgvSprite(curZone, agv, setCurSprite) + } + +} + +const showAgvSprite = (curZone, agv, setCurSprite) => { + const { agvNo, code, direction, backpack, battery, ...rest } = agv; + if (!code) { return } + const codeSprite = querySprite(DEVICE_TYPE.POINT, code); + if (!codeSprite) { return } + let agvSprite = querySprite(DEVICE_TYPE.AGV, agvNo); + if (!agvSprite) { + agvSprite = generateSprite(DEVICE_TYPE.AGV, + generateAgvSpriteTexture(getAgvStatusMode(backpack.filter(item => item.loaded === true).length, battery)) + ); + initSprite(agvSprite, DEVICE_TYPE.AGV); + agvSprite.data.no = agvNo; + agvSprite.position.set(codeSprite.position.x, codeSprite.position.y); + agvSprite.rotation = rotationParseNum(direction); + mapContainer.addChild(agvSprite); + beInsight(agvSprite, setCurSprite); + // agv no on sprite + } } \ No newline at end of file -- Gitblit v1.9.1