diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-07-16 17:37:01 +0200 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-07-16 17:37:01 +0200 |
| commit | f2aeecccc096728d3df955b71e711c8d9c429427 (patch) | |
| tree | 14494ef902f054a38f93af29976be81f8d5dba75 /opendc-web/opendc-web-ui/src/components/app/map/layers/HoverLayerComponent.js | |
| parent | e5caf6c6122684e441d1d73e2e0507fdd36c67e0 (diff) | |
refactor(ui): Isolate world coordinate space
This change updates the topology view in the OpenDC frontend to isolate
the world coordinate space. This means that zooming and panning should
not affect the coordinates in world space (but only in camera space). In
turn, this allows us to remove the dependency on Redux for the camera
controls.
Diffstat (limited to 'opendc-web/opendc-web-ui/src/components/app/map/layers/HoverLayerComponent.js')
| -rw-r--r-- | opendc-web/opendc-web-ui/src/components/app/map/layers/HoverLayerComponent.js | 67 |
1 files changed, 29 insertions, 38 deletions
diff --git a/opendc-web/opendc-web-ui/src/components/app/map/layers/HoverLayerComponent.js b/opendc-web/opendc-web-ui/src/components/app/map/layers/HoverLayerComponent.js index a88a8b34..2b1060c0 100644 --- a/opendc-web/opendc-web-ui/src/components/app/map/layers/HoverLayerComponent.js +++ b/opendc-web/opendc-web-ui/src/components/app/map/layers/HoverLayerComponent.js @@ -1,61 +1,52 @@ import PropTypes from 'prop-types' -import React, { useEffect, useState } from 'react' -import { Layer } from 'react-konva' +import React, { useMemo, useState } from 'react' +import { Layer } from 'react-konva/lib/ReactKonva' import HoverTile from '../elements/HoverTile' import { TILE_SIZE_IN_PIXELS } from '../MapConstants' +import { useEffectRef } from '../../../../util/effect-ref' -function HoverLayerComponent({ mouseX, mouseY, mapPosition, mapScale, isEnabled, isValid, onClick, children }) { - const [pos, setPos] = useState([-1, -1]) - const [x, y] = pos - const [valid, setValid] = useState(false) +function HoverLayerComponent({ isEnabled, isValid, onClick, children }) { + const [[mouseWorldX, mouseWorldY], setPos] = useState([0, 0]) - useEffect(() => { - if (!isEnabled()) { + const layerRef = useEffectRef((layer) => { + if (!layer) { return } - const positionX = Math.floor((mouseX - mapPosition.x) / (mapScale * TILE_SIZE_IN_PIXELS)) - const positionY = Math.floor((mouseY - mapPosition.y) / (mapScale * TILE_SIZE_IN_PIXELS)) + const stage = layer.getStage() - if (positionX !== x || positionY !== y) { - setPos([positionX, positionY]) - setValid(isValid(positionX, positionY)) - } - }, [isEnabled, isValid, x, y, mouseX, mouseY, mapPosition, mapScale]) + // Transform used to convert mouse coordinates to world coordinates + const transform = stage.getAbsoluteTransform().copy() + transform.invert() + + stage.on('mousemove.hover', () => { + const { x, y } = transform.point(stage.getPointerPosition()) + setPos([x, y]) + }) + return () => stage.off('mousemove.hover') + }) + + const gridX = Math.floor(mouseWorldX / TILE_SIZE_IN_PIXELS) + const gridY = Math.floor(mouseWorldY / TILE_SIZE_IN_PIXELS) + const valid = useMemo(() => isEnabled && isValid(gridX, gridY), [isEnabled, isValid, gridX, gridY]) - if (!isEnabled()) { + if (!isEnabled) { return <Layer /> } - const pixelX = mapScale * x * TILE_SIZE_IN_PIXELS + mapPosition.x - const pixelY = mapScale * y * TILE_SIZE_IN_PIXELS + mapPosition.y + const x = gridX * TILE_SIZE_IN_PIXELS + const y = gridY * TILE_SIZE_IN_PIXELS return ( - <Layer opacity={0.6}> - <HoverTile - pixelX={pixelX} - pixelY={pixelY} - scale={mapScale} - isValid={valid} - onClick={() => (valid ? onClick(x, y) : undefined)} - /> - {children - ? React.cloneElement(children, { - pixelX, - pixelY, - scale: mapScale, - }) - : undefined} + <Layer opacity={0.6} ref={layerRef}> + <HoverTile x={x} y={y} isValid={valid} onClick={() => (valid ? onClick(gridX, gridY) : undefined)} /> + {children ? React.cloneElement(children, { x, y, scale: 1 }) : undefined} </Layer> ) } HoverLayerComponent.propTypes = { - mouseX: PropTypes.number.isRequired, - mouseY: PropTypes.number.isRequired, - mapPosition: PropTypes.object.isRequired, - mapScale: PropTypes.number.isRequired, - isEnabled: PropTypes.func.isRequired, + isEnabled: PropTypes.bool.isRequired, isValid: PropTypes.func.isRequired, onClick: PropTypes.func.isRequired, children: PropTypes.node, |
