| | |
| | | import * as TWEEDLE from 'tweedle.js'; |
| | | import { |
| | | MAP_DEFAULT_ROTATION, |
| | | MAP_MIRROR, |
| | | DEVICE_TYPE, |
| | | DEVICE_Z_INDEX, |
| | | AGV_STATUS_MODE, |
| | |
| | | DEVICE_SELECTED_EFFECT_COLOR, |
| | | POINT_ROUTE_DIRECTION, |
| | | ANIMATE_DURING_TIME, |
| | | AGV_ANGLE_OFFSET_VAL, |
| | | } from './constants'; |
| | | import { getRouteList } from './http'; |
| | | import PointRoute from "./PointRoute"; |
| | |
| | | let batchMoveStartPos = null; |
| | | |
| | | const batchMoving = (event) => { |
| | | const scale = mapContainer.scale.x; |
| | | const scaleX = mapContainer.scale.x; |
| | | const scaleY = mapContainer.scale.y; |
| | | if (batchMove && batchMoveStartPos) { |
| | | // offset move val |
| | | var mouseMovement = { |
| | | x: (event.global.x - batchMoveStartPos.x) / scale, |
| | | y: (event.global.y - batchMoveStartPos.y) / scale |
| | | x: (event.global.x - batchMoveStartPos.x) / scaleX, |
| | | y: (event.global.y - batchMoveStartPos.y) / scaleY |
| | | }; |
| | | for (let sprite of selectedSprites) { |
| | | sprite.position.x = sprite.batchMoveStartPos.x + mouseMovement.x; |
| | | sprite.position.y = sprite.batchMoveStartPos.y + mouseMovement.y; |
| | | sprite.position.x = sprite.batchMoveStartPos.x - mouseMovement.x; |
| | | sprite.position.y = sprite.batchMoveStartPos.y - mouseMovement.y; |
| | | } |
| | | } |
| | | } |
| | |
| | | return; |
| | | } |
| | | |
| | | mapContainer.scale.set(0.3); |
| | | const focusScale = 0.1; |
| | | mapContainer.scale.set(MAP_MIRROR ? -focusScale : focusScale, focusScale); |
| | | mapContainer.position.set(0, 0); |
| | | |
| | | let bounds = sprite.getBounds(); |
| | |
| | | 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 showRoutes = (curZone, setShowRoutes, setLoading) => { |
| | | setLoading(true); |
| | | getRouteList( |
| | | curZone, |
| | | (routeList) => { |
| | | routeList.forEach(route => { |
| | | const startPoint = querySprite(DEVICE_TYPE.POINT, route.startCodeStr); |
| | | const endPoint = querySprite(DEVICE_TYPE.POINT, route.endCodeStr); |
| | | if (!startPoint || !endPoint) { |
| | | console.error("route", route) |
| | | console.error("start", startPoint) |
| | | console.error("end", endPoint) |
| | | } |
| | | const pointRoute = new PointRoute(POINT_ROUTE_DIRECTION[route.direction]); |
| | | pointRoute.setPoint(startPoint, endPoint); |
| | | pointRoute.clear(); |
| | | pointRoute.lineStyle(Math.max(7, 2 * (1 / Math.abs(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); |
| | | }) |
| | | setLoading(false); |
| | | setShowRoutes(true); |
| | | }, |
| | | () => { |
| | | setLoading(false); |
| | | }, |
| | | ) |
| | | }; |
| | | |
| | | export const hideRoutes = (curZone, setShowRoutes) => { |
| | |
| | | } |
| | | } |
| | | |
| | | export function createAgvJobPanel(parentContainer, text) { |
| | | const panelScale = 4; |
| | | |
| | | const panel = new PIXI.Container(); |
| | | |
| | | const sideLen = 50 * panelScale; |
| | | const halfCircle = new PIXI.Graphics(); |
| | | halfCircle.beginFill(themeMode === 'light' ? '#333333' : '#eee'); |
| | | halfCircle.lineStyle(2 * panelScale, themeMode === 'light' ? '#333333' : '#eee'); |
| | | halfCircle.arc(0, 0, sideLen, 0, Math.PI); |
| | | halfCircle.endFill(); |
| | | |
| | | const rectangle = new PIXI.Graphics(); |
| | | rectangle.lineStyle(2 * panelScale, themeMode === 'light' ? '#333333' : '#eee', .8); |
| | | rectangle.drawRoundedRect( |
| | | -sideLen / 2, // 左上角 x |
| | | -sideLen / 2, // 左上角 y |
| | | sideLen, // 宽 |
| | | sideLen - (20 * panelScale), // 高 (留一点空间,看起来更像半圆容器) |
| | | 16 * panelScale // 圆角 |
| | | ); |
| | | rectangle.endFill(); |
| | | rectangle.mask = halfCircle; |
| | | |
| | | panel.addChild(rectangle, halfCircle); |
| | | |
| | | const msg = new PIXI.Text(text, { |
| | | fill: themeMode === 'light' ? '#2b2b2b' : '#eee', |
| | | fontSize: 12 * panelScale, |
| | | fontFamily: 'MicrosoftYaHei', |
| | | fontWeight: 'bolder', |
| | | align: 'center', |
| | | }); |
| | | msg.anchor.set(0.5); |
| | | msg.position.set(0, -10 * panelScale); |
| | | |
| | | panel.addChild(msg); |
| | | parentContainer.addChild(panel); |
| | | |
| | | let phase = 0; |
| | | function onTick(delta) { |
| | | phase += delta / 6; // 旋转速度可调 |
| | | phase %= (Math.PI * 2); |
| | | halfCircle.rotation = phase; |
| | | } |
| | | app.ticker.add(onTick); |
| | | |
| | | panel._onTick = onTick; |
| | | return panel; |
| | | } |
| | | |
| | | // dynamic graphic ---------------- |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | const agvRotationOffsetDegrees = 90; |
| | | const agvRotationOffset = rotationParseNum(agvRotationOffsetDegrees); |
| | | const agvRotationOffset = rotationParseNum(AGV_ANGLE_OFFSET_VAL); |
| | | |
| | | const showAgvSprite = (curZone, agvVo, setCurSprite) => { |
| | | const { agvNo, code, direction, battery, backpack, error } = agvVo; |
| | | const { agvNo, code, direction, battery, jobType, backpack: backpackCount, slots, error } = 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; |
| | | // const backpackCount = backpack?.filter(item => item.loaded === true).length || 0; |
| | | |
| | | let agvSprite = querySprite(DEVICE_TYPE.AGV, agvNo); |
| | | if (!agvSprite) { |
| | |
| | | }); |
| | | agvText.anchor.set(0.5, 0.5); |
| | | agvText.position.set(0, 8); |
| | | agvText.scale.set(MAP_MIRROR ? -1 : 1, 1) |
| | | agvSprite.addChild(agvText); |
| | | |
| | | agvSprite.updateTextRotation = () => { |
| | |
| | | } |
| | | |
| | | animateRotation(agvSprite, targetRotation + agvRotationOffset, agvRotationOffset); |
| | | } |
| | | |
| | | // job effect |
| | | if (jobType) { |
| | | if (!agvSprite.data.jobEffect) { |
| | | agvSprite.data.jobEffect = createAgvJobPanel(agvSprite, jobType + " (" + backpackCount + "/" + slots + ")"); |
| | | agvSprite.data.jobEffect.x = -80; |
| | | agvSprite.data.jobEffect.y = 0; |
| | | } |
| | | if (agvSprite.data.jobEffect) { |
| | | agvSprite.data.jobEffect.rotation = -agvSprite.rotation - rotationParseNum(MAP_DEFAULT_ROTATION); |
| | | } |
| | | } else { |
| | | if (agvSprite.data.jobEffect) { |
| | | app.ticker.remove(agvSprite.data.jobEffect._onTick); |
| | | agvSprite.removeChild(agvSprite.data.jobEffect); |
| | | agvSprite.data.jobEffect.destroy(true); |
| | | agvSprite.data.jobEffect = null; |
| | | } |
| | | } |
| | | |
| | | if (error) { |
| | |
| | | return; |
| | | } |
| | | const { agvNo, code: curCode, dynamicRoute } = agvVo; |
| | | if (!dynamicRoute || dynamicRoute.indexOf(curCode) === -1) { |
| | | return; |
| | | } |
| | | |
| | | const agvPathName = 'agvPath-' + agvNo; |
| | | let agvPath = mapContainer.getChildByName(agvPathName); |
| | |
| | | } |
| | | agvPath = new PIXI.Graphics(); |
| | | agvPath.name = agvPathName; |
| | | agvPath.lineStyle(Math.max(20, 4 * (1 / mapContainer?.scale.x || 1)) |
| | | , themeMode === 'dark' ? 0x40739e : 0x2f68ac |
| | | , 0.8); |
| | | agvPath.lineStyle( |
| | | Math.max(200, 4 * (1 / mapContainer?.scale.x || 1)), |
| | | themeMode === 'dark' ? 0x40739e : 0x2f68ac, |
| | | 0.8, |
| | | ); |
| | | agvPath.zIndex = DEVICE_Z_INDEX.DYNAMIC_ROUTE; |
| | | // agvPath.blendMode = PIXI.BLEND_MODES.NORMAL; |
| | | |