| | |
| | | import * as React from 'react' |
| | | import * as PIXI from 'pixi.js'; |
| | | import { FormattedMessage, useIntl, useModel } from '@umijs/max'; |
| | | import { Layout, Button, Flex, Row, Col, FloatButton, Select, Spin } from 'antd'; |
| | | import { Layout, Button, Flex, Row, Col, FloatButton, Select, Spin, AutoComplete } from 'antd'; |
| | | const { Header, Content } = Layout; |
| | | import { |
| | | AppstoreAddOutlined, |
| | | FileAddOutlined, |
| | | CompressOutlined, |
| | | SettingOutlined, |
| | | CloseOutlined |
| | | } from '@ant-design/icons'; |
| | | import './index.css' |
| | | import { createStyles } from 'antd-style'; |
| | |
| | | import Settings from './components/settings' |
| | | import * as Utils from './utils' |
| | | import Player from './player'; |
| | | import MapSearch from './header/search'; |
| | | import MapDrawer from './drawer'; |
| | | |
| | | const useStyles = createStyles(({ token }) => { |
| | |
| | | select: { |
| | | color: 'red', |
| | | fontWeight: 'bold', |
| | | }, |
| | | headerCol: { |
| | | paddingLeft: '50px' |
| | | } |
| | | }; |
| | | }); |
| | |
| | | const mapRef = React.useRef(); |
| | | const contentRef = React.useRef(); |
| | | |
| | | const [model, setModel] = React.useState(() => MapModel.OBSERVER_MODEL); |
| | | const [model, setModel] = React.useState(null); |
| | | const [deviceVisible, setDeviceVisible] = React.useState(false); |
| | | const [settingsVisible, setSettingsVisible] = React.useState(false); |
| | | const [windowSize, setWindowSize] = React.useState({ |
| | |
| | | const [didClickSprite, setDidClickSprite] = React.useState(false); |
| | | const [spriteBySettings, setSpriteBySettings] = React.useState(null); |
| | | const prevSpriteBySettingsRef = React.useRef(); |
| | | const [drawerVisible, setDrawerVisible] = React.useState(false); |
| | | const [dataFetched, setDataFetched] = React.useState(false); |
| | | const [curSprite, setCurSPrite] = React.useState(null); |
| | | const prevCurSpriteRef = React.useRef(); |
| | | |
| | | // init func |
| | | React.useEffect(() => { |
| | | player = new Player(mapRef.current, styles.dark, didClickSprite); |
| | | setApp(player.app); |
| | | setMapContainer(player.mapContainer); |
| | | Utils.syncApp(player.app); |
| | | Utils.syncMapContainer(player.mapContainer); |
| | | const initialize = async () => { |
| | | player = new Player(mapRef.current, styles.dark, didClickSprite); |
| | | setApp(player.app); |
| | | setMapContainer(player.mapContainer); |
| | | Utils.syncApp(player.app); |
| | | Utils.syncMapContainer(player.mapContainer); |
| | | |
| | | const handleResize = () => { |
| | | setWindowSize({ |
| | | width: window.innerWidth, |
| | | height: window.innerHeight, |
| | | }); |
| | | }; |
| | | window.addEventListener('resize', handleResize); |
| | | const handleResize = () => { |
| | | setWindowSize({ |
| | | width: window.innerWidth, |
| | | height: window.innerHeight, |
| | | }); |
| | | }; |
| | | window.addEventListener('resize', handleResize); |
| | | await Utils.fetchMapData(intl); |
| | | setDataFetched(true); |
| | | setModel(MapModel.OBSERVER_MODEL) |
| | | setTimeout(() => { |
| | | player.adaptScreen(); |
| | | }, 200) |
| | | } |
| | | initialize(); |
| | | }, []); |
| | | |
| | | // resize |
| | |
| | | const height = contentRef.current.offsetHeight; |
| | | app.renderer.resize(width, height); |
| | | if (model !== MapModel.OBSERVER_MODEL) { |
| | | player.hideGridlines(); |
| | | player.showGridlines(); |
| | | } |
| | | }, [app, mapContainer, windowSize]) |
| | | |
| | | // model |
| | | React.useEffect(() => { |
| | | if (!mapContainer) { |
| | | if (!mapContainer && !dataFetched) { |
| | | return; |
| | | } |
| | | switch (model) { |
| | |
| | | player.activateMapEvent(null); |
| | | |
| | | Utils.removeSelectedEffect(); |
| | | setCurSPrite(null); |
| | | setDeviceVisible(false); |
| | | setSettingsVisible(false); |
| | | |
| | | mapContainer.children.forEach(child => { |
| | | child.off('pointerup'); |
| | | child.off('pointermove'); |
| | | child.off('pointerdown'); |
| | | child.off('click'); |
| | | Utils.viewFeature(child, setCurSPrite); |
| | | }) |
| | | break |
| | | case MapModel.MOVABLE_MODEL: |
| | |
| | | Utils.removeSelectedEffect(); |
| | | setSpriteBySettings(null); |
| | | setSettingsVisible(false); |
| | | setDrawerVisible(false); |
| | | |
| | | mapContainer.children.forEach(child => { |
| | | Utils.beMovable(child, setDidClickSprite); |
| | |
| | | player.activateMapEvent(null); |
| | | |
| | | setDeviceVisible(false); |
| | | setDrawerVisible(false); |
| | | |
| | | mapContainer.children.forEach(child => { |
| | | Utils.beSettings(child, setSpriteBySettings, setDidClickSprite); |
| | |
| | | mapContainer.addChild(sprite); |
| | | Utils.beMovable(sprite, setDidClickSprite); |
| | | }; |
| | | |
| | | // watch curSprite |
| | | React.useEffect(() => { |
| | | if (!mapContainer) { |
| | | return; |
| | | } |
| | | prevCurSpriteRef.current = curSprite; |
| | | if (curSprite && prevCurSprite !== curSprite) { |
| | | Utils.removeSelectedEffect(); |
| | | } |
| | | if (curSprite) { |
| | | if (model === MapModel.OBSERVER_MODEL) { |
| | | Utils.showSelectedEffect(curSprite) |
| | | setDrawerVisible(true) |
| | | } |
| | | } else { |
| | | Utils.removeSelectedEffect(); |
| | | } |
| | | }, [curSprite]); |
| | | const prevCurSprite = prevCurSpriteRef.current; |
| | | |
| | | // didClickSprite, stop triggers both sprite click and play's selection boxs |
| | | React.useEffect(() => { |
| | |
| | | }, [spriteBySettings]) |
| | | const prevSpriteBySettings = prevSpriteBySettingsRef.current; |
| | | |
| | | const settingsFinish = () => { |
| | | setSettingsVisible(false); |
| | | setSpriteBySettings(null); |
| | | const settingsFinish = (values, fn) => { |
| | | fn(); |
| | | // setSettingsVisible(false); |
| | | // setSpriteBySettings(null); |
| | | } |
| | | |
| | | return ( |
| | |
| | | <Layout className={styles.layout}> |
| | | <Header className={styles.header}> |
| | | <Row style={{ height: '100%' }}> |
| | | <Col span={8} style={{ backgroundColor: '#dcdde1' }}> |
| | | |
| | | |
| | | <Select |
| | | defaultValue="agv" |
| | | style={{ |
| | | width: 120, |
| | | }} |
| | | size={'large'} |
| | | onChange={(value, option) => { |
| | | console.log(value, option); |
| | | }} |
| | | options={[ |
| | | { |
| | | value: 'agv', |
| | | label: 'agv', |
| | | }, |
| | | { |
| | | value: 'crn', |
| | | label: 'crn', |
| | | }, |
| | | ]} |
| | | /> |
| | | |
| | | <Select |
| | | |
| | | // notFoundContent={loading ? <Spin size="small" /> : null} |
| | | |
| | | /> |
| | | |
| | | |
| | | <Col className={styles.headerCol} span={12} style={{}}> |
| | | {dataFetched && ( |
| | | <MapSearch |
| | | model={model} |
| | | setModel={setModel} |
| | | ModelEnum={MapModel} |
| | | curSprite={curSprite} |
| | | setCurSPrite={setCurSPrite} |
| | | setSpriteBySettings={setSpriteBySettings} |
| | | /> |
| | | )} |
| | | </Col> |
| | | <Col span={16} style={{ backgroundColor: '#3C40C6' }}> |
| | | <Col span={12} style={{ backgroundColor: styles.dark ? '#2C3A47' : '#4a69bd' }}> |
| | | <Flex className={styles.flex} gap={'large'} justify={'flex-end'} align={'center'}> |
| | | |
| | | {model === MapModel.OBSERVER_MODEL && ( |
| | | <> |
| | | <Button |
| | | className='map-header-button' |
| | | size={'large'} |
| | | onClick={async () => { |
| | | await Utils.fetchMapData(intl); |
| | | |
| | | player.hideGridlines(); |
| | | player.hideStarryBackground(); |
| | | |
| | | player.activateMapEvent(null); |
| | | |
| | | Utils.removeSelectedEffect(); |
| | | setCurSPrite(null); |
| | | setDeviceVisible(false); |
| | | setSettingsVisible(false); |
| | | setDrawerVisible(false); |
| | | |
| | | mapContainer.children.forEach(child => { |
| | | Utils.viewFeature(child, setCurSPrite); |
| | | }) |
| | | |
| | | }} |
| | | > |
| | | <FormattedMessage id='map.load' defaultMessage='加载地图' /> |
| | | </Button> |
| | | </> |
| | | )} |
| | | |
| | | {model !== MapModel.OBSERVER_MODEL && ( |
| | | <> |
| | | <Button |
| | | className='map-header-button' |
| | | size={'large'} |
| | | onClick={() => { |
| | | Utils.clearMapData(intl); |
| | | }} |
| | | > |
| | | <FormattedMessage id='map.clear' defaultMessage='清除地图' /> |
| | | </Button> |
| | | <Button |
| | | className='map-header-button' |
| | | size={'large'} |
| | | onClick={() => { |
| | | Utils.saveMapData(intl); |
| | | }} |
| | | > |
| | | <FormattedMessage id='map.save' defaultMessage='保存地图' /> |
| | | </Button> |
| | | </> |
| | | )} |
| | | |
| | | <Select |
| | | className={styles.select} |
| | | className='map-header-select' |
| | | size={'large'} |
| | | defaultValue={MapModel.OBSERVER_MODEL} |
| | | style={{ |
| | |
| | | > |
| | | <FloatButton |
| | | icon={<CompressOutlined />} |
| | | onClick={() => { |
| | | player.adaptScreen(); |
| | | }} |
| | | /> |
| | | <FloatButton.BackTop visibilityHeight={0} /> |
| | | </FloatButton.Group> |
| | | |
| | | <FloatButton.Group |
| | |
| | | </FloatButton.Group> |
| | | </div> |
| | | </Content> |
| | | </Layout> |
| | | </Layout > |
| | | |
| | | <MapDrawer |
| | | open={drawerVisible} |
| | | curSprite={curSprite} |
| | | refCurr={mapRef.current} |
| | | onCancel={() => { |
| | | setCurSPrite(null); |
| | | setDrawerVisible(false); |
| | | }} |
| | | /> |
| | | |
| | | <Edit |
| | | open={deviceVisible} |