|  |  |  | 
|---|
|  |  |  | import * as React from 'react' | 
|---|
|  |  |  | import * as PIXI from 'pixi.js'; | 
|---|
|  |  |  | import { FormattedMessage, useIntl, useModel } from '@umijs/max'; | 
|---|
|  |  |  | import { Layout, Button, Flex, } from 'antd'; | 
|---|
|  |  |  | import { Layout, Button, Flex, Row, Col, FloatButton } from 'antd'; | 
|---|
|  |  |  | const { Header, Content } = Layout; | 
|---|
|  |  |  | import { | 
|---|
|  |  |  | AppstoreAddOutlined, | 
|---|
|  |  |  | FileAddOutlined, | 
|---|
|  |  |  | CompressOutlined, | 
|---|
|  |  |  | } from '@ant-design/icons'; | 
|---|
|  |  |  | import './index.css' | 
|---|
|  |  |  | import { createStyles } from 'antd-style'; | 
|---|
|  |  |  | import Edit from './components/edit' | 
|---|
|  |  |  | import Edit from './components/device' | 
|---|
|  |  |  | import * as Utils from './utils' | 
|---|
|  |  |  | import Player from './player'; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const useStyles = createStyles(({ token }) => { | 
|---|
|  |  |  | let dark = token.colorBgBase === '#000'; | 
|---|
|  |  |  | return { | 
|---|
|  |  |  | dark: dark, | 
|---|
|  |  |  | layout: { | 
|---|
|  |  |  | overflow: 'hidden', | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | 
|---|
|  |  |  | content: { | 
|---|
|  |  |  | backgroundColor: '#F8FAFB', | 
|---|
|  |  |  | height: 'calc(100vh - 120px)' | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | let player; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const Map = () => { | 
|---|
|  |  |  | const { initialState, setInitialState } = useModel('@@initialState'); | 
|---|
|  |  |  | 
|---|
|  |  |  | const mapRef = React.useRef(); | 
|---|
|  |  |  | const contentRef = React.useRef(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const [editModalVisible, setEditModalVisible] = React.useState(false); | 
|---|
|  |  |  | const [deviceVisible, setDeviceVisible] = React.useState(false); | 
|---|
|  |  |  | const [windowSize, setWindowSize] = React.useState({ | 
|---|
|  |  |  | width: window.innerWidth, | 
|---|
|  |  |  | height: window.innerHeight, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | const [app, setApp] = React.useState(null) | 
|---|
|  |  |  | const [mapContainer, setMapContainer] = React.useState(null) | 
|---|
|  |  |  | const [app, setApp] = React.useState(null); | 
|---|
|  |  |  | const [mapContainer, setMapContainer] = React.useState(null); | 
|---|
|  |  |  | const [mapEditModel, setMapEditModel] = React.useState(false); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | React.useEffect(() => { | 
|---|
|  |  |  | const player = new Player(mapRef.current); | 
|---|
|  |  |  | player = new Player(mapRef.current, styles.dark); | 
|---|
|  |  |  | setApp(player.app); | 
|---|
|  |  |  | setMapContainer(player.mapContainer); | 
|---|
|  |  |  | Utils.syncApp(player.app); | 
|---|
|  |  |  | 
|---|
|  |  |  | app.renderer.resize(width, height); | 
|---|
|  |  |  | }, [app, mapContainer, windowSize]) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const editHandle = () => { | 
|---|
|  |  |  | setEditModalVisible(true); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | React.useEffect(() => { | 
|---|
|  |  |  | if (!mapContainer) { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if (mapEditModel) { | 
|---|
|  |  |  | player.showGridlines(); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | player.hideGridlines(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, [mapEditModel]); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const onDrop = (sprite, x, y) => { | 
|---|
|  |  |  | const { mapX, mapY } = Utils.getRealPosition(x, y, mapContainer); | 
|---|
|  |  |  | 
|---|
|  |  |  | <> | 
|---|
|  |  |  | <Layout className={styles.layout}> | 
|---|
|  |  |  | <Header className={styles.header}> | 
|---|
|  |  |  | <Flex className={styles.flex} gap={'large'} justify={'flex-end'} align={'center'}> | 
|---|
|  |  |  | <Button onClick={editHandle} size={'large'}><FormattedMessage id='map.edit' defaultMessage='编辑地图' /></Button> | 
|---|
|  |  |  | </Flex> | 
|---|
|  |  |  | <Row style={{ height: '100%' }}> | 
|---|
|  |  |  | <Col span={8} style={{ backgroundColor: '#3C40C6' }}></Col> | 
|---|
|  |  |  | <Col span={16} style={{ backgroundColor: '#3C40C6' }}> | 
|---|
|  |  |  | <Flex className={styles.flex} gap={'large'} justify={'flex-end'} align={'center'}> | 
|---|
|  |  |  | <Button onClick={() => setMapEditModel(!mapEditModel)} size={'large'}> | 
|---|
|  |  |  | {!mapEditModel | 
|---|
|  |  |  | ? <span style={{ fontWeight: 'bold' }}><FormattedMessage id='map.edit' defaultMessage='编辑地图' /></span> | 
|---|
|  |  |  | : <span style={{ color: 'red', fontWeight: 'bold' }}><FormattedMessage id='map.edit.close' defaultMessage='退出编辑' /></span> | 
|---|
|  |  |  | } | 
|---|
|  |  |  | </Button> | 
|---|
|  |  |  | </Flex> | 
|---|
|  |  |  | </Col> | 
|---|
|  |  |  | </Row> | 
|---|
|  |  |  | </Header> | 
|---|
|  |  |  | <Content ref={contentRef} className={styles.content}> | 
|---|
|  |  |  | <div ref={mapRef} style={{ position: "relative" }} /> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <FloatButton.Group | 
|---|
|  |  |  | shape="square" | 
|---|
|  |  |  | style={{ | 
|---|
|  |  |  | left: 35, | 
|---|
|  |  |  | bottom: 35 | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | > | 
|---|
|  |  |  | <FloatButton | 
|---|
|  |  |  | icon={<CompressOutlined />} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | <FloatButton.BackTop visibilityHeight={0} /> | 
|---|
|  |  |  | </FloatButton.Group> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <FloatButton.Group | 
|---|
|  |  |  | hidden={!mapEditModel} | 
|---|
|  |  |  | trigger="hover" | 
|---|
|  |  |  | style={{ | 
|---|
|  |  |  | right: 35, | 
|---|
|  |  |  | bottom: 35 | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | icon={<AppstoreAddOutlined />} | 
|---|
|  |  |  | > | 
|---|
|  |  |  | <FloatButton | 
|---|
|  |  |  | tooltip={<div><FormattedMessage id='map.device.add' defaultMessage='添加设备' /></div>} | 
|---|
|  |  |  | icon={<FileAddOutlined />} | 
|---|
|  |  |  | onClick={() => { | 
|---|
|  |  |  | setDeviceVisible(true); | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </FloatButton.Group> | 
|---|
|  |  |  | </Content> | 
|---|
|  |  |  | </Layout> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <Edit | 
|---|
|  |  |  | open={editModalVisible} | 
|---|
|  |  |  | open={deviceVisible} | 
|---|
|  |  |  | onCancel={() => { | 
|---|
|  |  |  | setEditModalVisible(false); | 
|---|
|  |  |  | setDeviceVisible(false); | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | refCurr={mapRef.current} | 
|---|
|  |  |  | onDrop={onDrop} | 
|---|