From 7f70cb15d035f0c233b9e62b9e43aa985317c908 Mon Sep 17 00:00:00 2001 From: luxiaotao1123 <t1341870251@163.com> Date: 星期一, 04 十一月 2024 10:22:45 +0800 Subject: [PATCH] # --- zy-acs-flow/src/map/tool.js | 701 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 633 insertions(+), 68 deletions(-) diff --git a/zy-acs-flow/src/map/tool.js b/zy-acs-flow/src/map/tool.js index d8ea096..2993d4e 100644 --- a/zy-acs-flow/src/map/tool.js +++ b/zy-acs-flow/src/map/tool.js @@ -3,29 +3,72 @@ import { DEVICE_TYPE, DEVICE_Z_INDEX, + AGV_STATUS_MODE, + DEVICE_SPRITE_TINT, + DEVICE_SELECTED_EFFECT_PADDING, + DEVICE_SELECTED_EFFECT_COLOR, + POINT_ROUTE_DIRECTION, + DEVICE_SPRITE_TINT_DARK, } from './constants'; +import { getRouteList } from './http'; +import PointRoute from "./PointRoute"; import shelf from '/map/shelf.svg'; import charge from '/map/charge.svg'; +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; +let app, mapContainer, themeMode; +let selectedSprite, effectCircle, effectTicker; +let tooltip; + +export function getApp() { + return app; +} export function setApp(param) { app = param; +} + +export function getMapContainer() { + return mapContainer; } export function setMapContainer(param) { mapContainer = param; } -export function getApp() { - return app; +export function getThemeMode() { + return themeMode; } -export function getMapContainer() { - return mapContainer; +export function setThemeMode(param) { + themeMode = param; + if (mapContainer) { + // mapContainer.children.forEach(child => { + // const deviceType = child.data?.type; + // if (deviceType) { + // if (themeMode === 'dark') { + // const tint = DEVICE_SPRITE_TINT_DARK[deviceType] + // if (tint) { + // child.tint = tint; + // } + // } else { + // DEVICE_SPRITE_TINT[deviceType] != null && (child.tint = DEVICE_SPRITE_TINT[deviceType]); + // } + // } + // }) + } } + export const getRealPosition = (x, y) => { const rect = app.view.getBoundingClientRect(); @@ -35,41 +78,85 @@ } } -export const generateSprite = (deviceType) => { +export const generateSprite = (deviceType, texture) => { let sprite; switch (deviceType) { case DEVICE_TYPE.SHELF: - sprite = new PIXI.Sprite(PIXI.Texture.from(shelf, { resourceOptions: { scale: 5 } })); - sprite.width = 50; - sprite.height = 50; + sprite = new PIXI.Sprite(PIXI.Texture.from(shelf, { resourceOptions: { scale: 1 } })); + // sprite.width = 50; + // sprite.height = 50; sprite.zIndex = DEVICE_Z_INDEX.SHELF; break; case DEVICE_TYPE.CHARGE: sprite = new PIXI.Sprite(PIXI.Texture.from(charge, { resourceOptions: { scale: 1 } })); - sprite.width = 60; - sprite.height = 60; + // sprite.width = 60; + // sprite.height = 60; sprite.zIndex = DEVICE_Z_INDEX.CHARGE; break; + case DEVICE_TYPE.STATION: + sprite = new PIXI.Sprite(PIXI.Texture.from(station, { resourceOptions: { scale: 1 } })); + // sprite.width = 112; + // sprite.height = 63; + sprite.zIndex = DEVICE_Z_INDEX.STATION; + break; case DEVICE_TYPE.DIRECTION: - sprite = new PIXI.Sprite(PIXI.Texture.from(direction, { resourceOptions: { scale: 5 } })); - sprite.width = 112; - sprite.height = 63; + sprite = new PIXI.Sprite(PIXI.Texture.from(direction, { resourceOptions: { scale: 1 } })); + // sprite.width = 112; + // sprite.height = 63; sprite.zIndex = DEVICE_Z_INDEX.DIRECTION; break; + + + case DEVICE_TYPE.AGV: + if (texture) { + sprite = new PIXI.Sprite(PIXI.Texture.from(texture, { resourceOptions: { scale: 1 } })); + } + sprite.width = 400; + sprite.height = 700; + 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; + // sprite.height = 63; + sprite.zIndex = DEVICE_Z_INDEX.POINT; + break default: break; + } + const tintType = themeMode === 'dark' ? DEVICE_SPRITE_TINT_DARK : DEVICE_SPRITE_TINT; + tintType[deviceType] != null && (sprite.tint = tintType[deviceType]); + + if (sprite && deviceType !== DEVICE_TYPE.AGV) { + sprite.blendMode = PIXI.BLEND_MODES.MULTIPLY; } return sprite; } export const initSprite = (sprite, type) => { sprite.anchor.set(0.5); + // sprite.alpha = 1; sprite.cursor = 'pointer'; sprite.eventMode = 'static'; sprite.data = { type: type, uuid: generateID() }; +} + +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) => { @@ -80,10 +167,107 @@ sprite.alpha = 1; } +export const spriteListBeMovable = (selectedSprites, endFn) => { + if (selectedSprites && selectedSprites.length > 0) { + let batchMove = false; + let batchMoveStartPos = null; + + const batchMoving = (event) => { + const scale = mapContainer.scale.x; + if (batchMove && batchMoveStartPos) { + // offset move val + var mouseMovement = { + x: (event.global.x - batchMoveStartPos.x) / scale, + y: (event.global.y - batchMoveStartPos.y) / scale + }; + for (let sprite of selectedSprites) { + sprite.position.x = sprite.batchMoveStartPos.x + mouseMovement.x; + sprite.position.y = sprite.batchMoveStartPos.y + mouseMovement.y; + } + } + } + + const batchMoveEnd = (event) => { + batchMove = false; + batchMoveStartPos = null; + selectedSprites.forEach(child => { + unMarkSprite(child); + }) + selectedSprites = []; + mapContainer.parent.off('mousedown'); + mapContainer.parent.off('mousemove'); + mapContainer.parent.off('mouseup'); + + if (endFn) { + endFn(); + } + } + + const batchMoveStart = (event) => { + batchMoveStartPos = { x: event.data.global.clone().x, y: event.data.global.clone().y }; + selectedSprites.forEach(child => { + child.batchMoveStartPos = { x: child.position.x, y: child.position.y }; + }) + + batchMove = true; + mapContainer.parent.off('mousemove'); + mapContainer.parent.on('mousemove', batchMoving); + + mapContainer.parent.off('mouseup'); + mapContainer.parent.on('mouseup', batchMoveEnd); + } + + mapContainer.parent.off('mousedown') + mapContainer.parent.on('mousedown', batchMoveStart); + } +} + +export const copySprite = (sprite) => { + const copiedSprite = generateSprite(sprite.data.type) + initSprite(copiedSprite); + copiedSprite.position.set(sprite.position.x, sprite.position.y); + copiedSprite.scale.set(sprite.scale.x, sprite.scale.y); + copiedSprite.rotation = sprite.rotation; + copiedSprite.data = deepCopy(sprite.data); + copiedSprite.data.uuid = generateID(); + return copiedSprite; +} + +export const isSpriteInSelectionBox = (sprite, selectionBox) => { + const spriteBounds = sprite.getBounds(); + const boxBounds = selectionBox.getBounds(); + + return spriteBounds.x + spriteBounds.width > boxBounds.x + && spriteBounds.x < boxBounds.x + boxBounds.width + && spriteBounds.y + spriteBounds.height > boxBounds.y + && spriteBounds.y < boxBounds.y + boxBounds.height; +} + +export const beInsight = (sprite, setCurSprite) => { + if (!sprite?.data?.type) { return } + + sprite.off('pointerup'); + sprite.off('pointermove'); + sprite.off('pointerdown'); + sprite.off('pointerover'); + sprite.off('pointerout'); + sprite.off('click'); + + sprite.on("click", (event) => { + setCurSprite(sprite); + }); + + sprite.on('pointerover', onSpriteMouseOver); + sprite.on('pointermove', onSpriteMouseMove); + sprite.on('pointerout', onSpriteMouseOut); +} + export const beMovable = (sprite) => { sprite.off('pointerup'); sprite.off('pointermove'); sprite.off('pointerdown'); + sprite.off('pointerover'); + sprite.off('pointerout'); sprite.off('click'); sprite.on("pointerdown", onDragStart); @@ -117,74 +301,299 @@ } -export const spriteListBeMovable = (selectedSprites, resetFn) => { - if (selectedSprites && selectedSprites.length > 0) { - let batchMove = false; - let batchMoveStartPos = null; +export const beSettings = (sprite, setSpriteSettings) => { + if (!sprite?.data?.type) { return } - const batchMoving = (event) => { - const scale = mapContainer.scale.x; - if (batchMove && batchMoveStartPos) { - // offset move val - var mouseMovement = { - x: (event.global.x - batchMoveStartPos.x) / scale, - y: (event.global.y - batchMoveStartPos.y) / scale - }; - for (let sprite of selectedSprites) { - sprite.position.x = sprite.batchMoveStartPos.x + mouseMovement.x; - sprite.position.y = sprite.batchMoveStartPos.y + mouseMovement.y; - } - } - } + sprite.off('pointerup'); + sprite.off('pointermove'); + sprite.off('pointerdown'); + sprite.off('pointerover'); + sprite.off('pointerout'); + sprite.off('click'); - const batchMoveEnd = (event) => { - batchMove = false; - batchMoveStartPos = null; - selectedSprites.forEach(child => { - unMarkSprite(child); - }) - selectedSprites = []; - mapContainer.parent.off('mousedown'); - mapContainer.parent.off('mousemove'); - mapContainer.parent.off('mouseup'); + sprite.on("click", (event) => { + setSpriteSettings(sprite); + }); - if (resetFn) { - resetFn(); - } - } + sprite.on('pointerover', onSpriteMouseOver); + sprite.on('pointermove', onSpriteMouseMove); + sprite.on('pointerout', onSpriteMouseOut); +} - const batchMoveStart = (event) => { - batchMoveStartPos = { x: event.data.global.clone().x, y: event.data.global.clone().y }; - selectedSprites.forEach(child => { - child.batchMoveStartPos = { x: child.position.x, y: child.position.y }; - }) +const createSpriteTooltip = (sprite) => { + const style = new PIXI.TextStyle({ + fontFamily: 'Roboto', + fontSize: 12, + fill: themeMode === 'light' ? '#000' : '#eee', + }); + const text = new PIXI.Text(`${sprite.data?.type} ${sprite.data?.no}`, style); + const background = new PIXI.Graphics(); + // shadow + background.beginFill(themeMode === 'light' ? '#000' : '#eee', 0.1); + background.drawRoundedRect(4, 4, text.width + 6, text.height + 6, 4); + background.endFill(); + // background + background.beginFill(themeMode === 'light' ? '#fff' : '#333', 1); + background.drawRoundedRect(0, 0, text.width + 8, text.height + 8, 4); + background.endFill(); - batchMove = true; - mapContainer.parent.off('mousemove'); - mapContainer.parent.on('mousemove', batchMoving); + text.x = 5; + text.y = 3; + background.addChild(text); + tooltip = new PIXI.Container(); + tooltip.name = "tooltip"; + tooltip.addChild(background); + return tooltip; +} - mapContainer.parent.off('mouseup'); - mapContainer.parent.on('mouseup', batchMoveEnd); - } +function onSpriteMouseOver(event) { + if (tooltip) { + app?.stage.removeChild(tooltip); + } + tooltip = createSpriteTooltip(this);// this => sprite + tooltip.x = event.data.global.x + 10; + tooltip.y = event.data.global.y + 10; + app.stage.addChild(tooltip); +} - mapContainer.parent.off('mousedown') - mapContainer.parent.on('mousedown', batchMoveStart); +function onSpriteMouseMove(event) { + if (tooltip) { + tooltip.x = event.data.global.x + 10; + tooltip.y = event.data.global.y + 10; } } -export const isSpriteInSelectionBox = (sprite, selectionBox) => { - const spriteBounds = sprite.getBounds(); - const boxBounds = selectionBox.getBounds(); - - return spriteBounds.x + spriteBounds.width > boxBounds.x - && spriteBounds.x < boxBounds.x + boxBounds.width - && spriteBounds.y + spriteBounds.height > boxBounds.y - && spriteBounds.y < boxBounds.y + boxBounds.height; +function onSpriteMouseOut() { + if (tooltip && tooltip.parent) { + tooltip.parent?.removeChild(tooltip); + tooltip = null; + } } +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 = () => { + if (!mapContainer) { + return; + } + let childList = []; + mapContainer.children.forEach(child => { + if (child.data?.uuid) { + childList.push(child); + } + }) + if (childList.length > 0) { + childList.forEach(child => { + mapContainer.removeChild(child); + child.destroy({ children: true, texture: false, baseTexture: false }); + }) + childList.forEach((child, index) => { + childList[index] = null; + }); + childList = []; + } +} + +export const showSelectedEffect = (sprite) => { + if (!sprite?.texture || !sprite?.texture?.valid) { + return; + } + + const { width, height } = sprite; + const maxDimension = Math.max(width, height); + const radius = (maxDimension / 2) + (DEVICE_SELECTED_EFFECT_PADDING[sprite.data?.type] || 10); + + let color; + const spriteEffectColor = DEVICE_SELECTED_EFFECT_COLOR[sprite.data?.type]; + if (spriteEffectColor) { + color = spriteEffectColor; + } else { + color = themeMode === 'light' ? '#747d8c' : '#718093'; + } + + const alpha = 1; + + effectCircle = new PIXI.Graphics(); + effectCircle.beginFill(color, alpha); + effectCircle.drawCircle(0, 0, radius); + effectCircle.endFill(); + effectCircle.position.set(sprite.x, sprite.y); + effectCircle.zIndex = -1; + effectCircle.blendMode = PIXI.BLEND_MODES.NORMAL; + + mapContainer.addChild(effectCircle); + + selectedSprite = sprite; + + let pulseScale = 1; + let scalingUp = true; + effectTicker = (delta) => { + const pulseSpeed = 0.003 * delta; + if (scalingUp) { + pulseScale += pulseSpeed; + if (pulseScale >= 1.1) { + scalingUp = false; + } + } else { + pulseScale -= pulseSpeed; + if (pulseScale <= 1) { + scalingUp = true; + } + } + effectCircle.scale.set(pulseScale); + effectCircle.position.set(sprite.x, sprite.y); + }; + + app.ticker.add(effectTicker); +}; + +export const removeSelectedEffect = () => { + if (effectTicker) { + app.ticker.remove(effectTicker); + effectTicker = null; + } + if (effectCircle) { + mapContainer?.removeChild(effectCircle); + effectCircle = null; + } + selectedSprite = null; +}; + +export const updateEffect = () => { + if (!selectedSprite || !effectCircle) { + return; + } + effectCircle.position.set(selectedSprite.x, selectedSprite.y); +}; + +export const showRoutes = (curZone, setShowRoutes) => { + setShowRoutes(true); + getRouteList(curZone, (routeList) => { + routeList.forEach(route => { + const startPoint = querySprite(DEVICE_TYPE.POINT, route.startCodeStr); + const endPoint = querySprite(DEVICE_TYPE.POINT, route.endCodeStr); + const pointRoute = new PointRoute(POINT_ROUTE_DIRECTION[route.direction]); + pointRoute.setPoint(startPoint, endPoint); + pointRoute.clear(); + pointRoute.lineStyle(Math.max(7, 2 * (1 / mapContainer.scale.x)), themeMode === 'light' ? '#ced6e0' : '#535c68'); + pointRoute.moveTo(startPoint.position.x, startPoint.position.y); + pointRoute.lineTo(endPoint.position.x, endPoint.position.y); + pointRoute.alpha = 1; + mapContainer.addChild(pointRoute); + }) + }) +}; + +export const hideRoutes = (curZone, setShowRoutes) => { + setShowRoutes(false); + for (let i = mapContainer.children.length - 1; i >= 0; i--) { + const child = mapContainer.children[i]; + if (child?.type === DEVICE_TYPE.ROUTE) { + mapContainer.removeChild(child); + } + } +} + +export const multipleSelectEnhancer = (selectedSprites, setCurSprite, setBatchSprites) => { + selectedSprites = selectedSprites.filter(sprite => sprite.data?.type); + + if (selectedSprites.length === 1) { + unMarkSprite(selectedSprites[0]); + setCurSprite(selectedSprites[0]); + } else { + setBatchSprites(selectedSprites); + } +} + +export const rotationToNum = (rotation) => { + let res = rotation * 180 / Math.PI; + if (res < 0) { + res += 360; + } else if (res > 360) { + res -= 360; + } + return res; +} + +export const rotationParseNum = (num) => { + return num * (Math.PI / 180); +} + +const animateRotation = (sprite, targetRotation, rotationOffset = 0) => { + if (!mapContainer || !sprite) { + return; + } + // origin + let currentRotation = sprite.rotation + rotationOffset; + // target + targetRotation += rotationOffset; + + // diff + let rotationDifference = targetRotation - currentRotation; + if (rotationDifference === 0) { + return; + } + rotationDifference = ((rotationDifference + Math.PI) % (2 * Math.PI)) - Math.PI; + + // destination + const endRotation = sprite.rotation + rotationDifference; + + new TWEEDLE.Tween(sprite) + .to({ rotation: endRotation }, 1000) + .easing(TWEEDLE.Easing.Linear.None) + .onUpdate(() => { + // agv + if (sprite.updateTextRotation) { + sprite.updateTextRotation(); + } + }) + .start(); +}; + +export const incrementSpriteNo = (str, incrementValue) => { + const match = str.match(/(\D*)(\d+)/); + if (match) { + const prefix = match[1]; + const numberPart = match[2]; + const newNumber = parseInt(numberPart, 10) + incrementValue; + const paddedNumber = newNumber.toString().padStart(numberPart.length, '0'); + return `${prefix}${paddedNumber}`; + } else { + return str; + } +} export const generateID = () => { return Date.now().toString(36) + Math.random().toString(36).substring(2); +} + +export const deepCopy = (data) => { + return JSON.parse(JSON.stringify(data)); } export const patchRaLayout = (param) => { @@ -193,4 +602,160 @@ parentElement.style.paddingLeft = param; parentElement.style.paddingRight = param; } -} \ No newline at end of file +} + + +// 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) => { + for (const agvVo of data.agvVos) { + showAgvSprite(curZone, agvVo, setCurSprite); + drawerAgvPath(curZone, agvVo); + } +} + +const agvRotationOffsetDegrees = 0; +const agvRotationOffset = rotationParseNum(agvRotationOffsetDegrees); + +const showAgvSprite = (curZone, agvVo, setCurSprite) => { + const { agvNo, code, direction, battery, backpack } = agvVo; + if (!code) { return; } + const codeSprite = querySprite(DEVICE_TYPE.POINT, code); + if (!codeSprite) { return; } + + const targetRotation = rotationParseNum(direction); + const backpackCount = backpack?.filter(item => item.loaded === true).length || 0; + + let agvSprite = querySprite(DEVICE_TYPE.AGV, agvNo); + if (!agvSprite) { + const agvStatusMode = getAgvStatusMode(backpackCount, battery); + const agvTexture = generateAgvSpriteTexture(agvStatusMode); + agvSprite = generateSprite(DEVICE_TYPE.AGV, agvTexture); + + initSprite(agvSprite, DEVICE_TYPE.AGV); + + agvSprite.data.no = agvNo; + agvSprite.data.backpackCount = backpackCount; + agvSprite.data.battery = battery; + + agvSprite.position.set(codeSprite.position.x, codeSprite.position.y); + agvSprite.rotation = targetRotation + agvRotationOffset; + mapContainer.addChild(agvSprite); + beInsight(agvSprite, setCurSprite); + + // agvNo sprite + const agvText = new PIXI.Text(agvNo.toString(), { + fontSize: 60, + fill: 0x000000, + }); + agvText.anchor.set(0.5, 0.5); + agvText.position.set(0, 0); + agvSprite.addChild(agvText); + + agvSprite.updateTextRotation = () => { + if (agvText && agvSprite) { + agvText.rotation = -agvSprite.rotation; + } + }; + agvSprite.updateTextRotation(); + + } else { + const prevBackpackCount = agvSprite.data.backpackCount; + const prevBattery = agvSprite.data.battery; + + if (backpackCount !== prevBackpackCount || battery !== prevBattery) { + const agvStatusMode = getAgvStatusMode(backpackCount, battery); + const agvTexture = generateAgvSpriteTexture(agvStatusMode); + agvSprite.texture = PIXI.Texture.from(agvTexture, { resourceOptions: { scale: 1 } }); + // update backpackCount and battery + agvSprite.data.backpackCount = backpackCount; + agvSprite.data.battery = battery; + } + + animateRotation(agvSprite, targetRotation, agvRotationOffset); + } + + new TWEEDLE.Tween(agvSprite.position) + .to({ + x: codeSprite.position.x, + y: codeSprite.position.y + }, 1000) + .easing(TWEEDLE.Easing.Linear.None) + .start(); +} + +const drawerAgvPath = (curZone, agvVo) => { + if (!mapContainer) { + return; + } + const { agvNo, code: curCode, dynamicRoute } = agvVo; + + const agvPathName = 'agvPath-' + agvNo; + let agvPath = mapContainer.getChildByName(agvPathName); + if (agvPath) { + mapContainer.removeChild(agvPath); + } + agvPath = new PIXI.Graphics(); + agvPath.name = agvPathName; + agvPath.lineStyle(Math.max(20, 4 * (1 / mapContainer.scale.x)), 0x2f68ac, 0.8); + agvPath.zIndex = DEVICE_Z_INDEX.DYNAMIC_ROUTE; + // agvPath.blendMode = PIXI.BLEND_MODES.NORMAL; + + let firstNode = true; + for (let i = Math.max(0, dynamicRoute.indexOf(curCode)); i < dynamicRoute.length; i++) { + const node = dynamicRoute[i]; + const codeSprite = querySprite(DEVICE_TYPE.POINT, node); + if (!codeSprite) { continue }; + const { x, y } = codeSprite.position; + if (firstNode) { + agvPath.moveTo(x, y); + firstNode = false; + } else { + agvPath.lineTo(x, y); + } + } + + mapContainer.addChild(agvPath); +} -- Gitblit v1.9.1