From 3ccc6c95acfe71fee5884ccb32c685adc53127cf Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Tue, 26 Sep 2017 19:34:17 +0200 Subject: Refactor zooming logic out to action This also enables a more straight-forward implementation of the functionality that the zoom buttons offer. --- src/actions/map.js | 50 ++++++++++++++++++++++ src/components/app/map/MapStageComponent.js | 41 +++--------------- .../app/map/controls/ZoomControlComponent.js | 13 ++---- src/containers/app/map/MapStage.js | 7 ++- .../app/map/controls/ZoomControlContainer.js | 4 +- 5 files changed, 64 insertions(+), 51 deletions(-) diff --git a/src/actions/map.js b/src/actions/map.js index ef691873..47d4714d 100644 --- a/src/actions/map.js +++ b/src/actions/map.js @@ -1,3 +1,10 @@ +import { + MAP_MAX_SCALE, + MAP_MIN_SCALE, + MAP_SCALE_PER_EVENT, + MAP_SIZE_IN_PIXELS +} from "../components/app/map/MapConstants"; + export const SET_MAP_POSITION = "SET_MAP_POSITION"; export const SET_MAP_DIMENSIONS = "SET_MAP_DIMENSIONS"; export const SET_MAP_SCALE = "SET_MAP_SCALE"; @@ -24,3 +31,46 @@ export function setMapScale(scale) { scale }; } + +export function zoomInOnCenter(zoomIn) { + return (dispatch, getState) => { + const state = getState(); + + dispatch(zoomInOnPosition(zoomIn, state.map.dimensions.width / 2, state.map.dimensions.height / 2)); + } +} + +export function zoomInOnPosition(zoomIn, x, y) { + return (dispatch, getState) => { + const state = getState(); + + const centerPoint = { + x: x / state.map.scale - state.map.position.x / state.map.scale, + y: y / state.map.scale - state.map.position.y / state.map.scale, + }; + const newScale = zoomIn ? state.map.scale * MAP_SCALE_PER_EVENT : state.map.scale / MAP_SCALE_PER_EVENT; + const boundedScale = Math.min(Math.max(MAP_MIN_SCALE, newScale), MAP_MAX_SCALE); + + const newX = -(centerPoint.x - x / boundedScale) * boundedScale; + const newY = -(centerPoint.y - y / boundedScale) * boundedScale; + + dispatch(setMapPositionWithBoundsCheck(newX, newY)); + dispatch(setMapScale(boundedScale)); + } +} + +export function setMapPositionWithBoundsCheck(x, y) { + return (dispatch, getState) => { + const state = getState(); + + const scaledMapSize = MAP_SIZE_IN_PIXELS * state.map.scale; + const updatedX = x > 0 ? 0 : + (x < -scaledMapSize + state.map.dimensions.width + ? -scaledMapSize + state.map.dimensions.width : x); + const updatedY = y > 0 ? 0 : + (y < -scaledMapSize + state.map.dimensions.height + ? -scaledMapSize + state.map.dimensions.height : y); + + dispatch(setMapPosition(updatedX, updatedY)); + } +} diff --git a/src/components/app/map/MapStageComponent.js b/src/components/app/map/MapStageComponent.js index b8e3c3f7..20389758 100644 --- a/src/components/app/map/MapStageComponent.js +++ b/src/components/app/map/MapStageComponent.js @@ -6,13 +6,7 @@ import ObjectHoverLayer from "../../../containers/app/map/layers/ObjectHoverLaye import RoomHoverLayer from "../../../containers/app/map/layers/RoomHoverLayer"; import jQuery from "../../../util/jquery"; import {NAVBAR_HEIGHT} from "../../navigation/Navbar"; -import { - MAP_MAX_SCALE, - MAP_MIN_SCALE, - MAP_MOVE_PIXELS_PER_EVENT, - MAP_SCALE_PER_EVENT, - MAP_SIZE_IN_PIXELS -} from "./MapConstants"; +import {MAP_MOVE_PIXELS_PER_EVENT} from "./MapConstants"; class MapStageComponent extends React.Component { state = { @@ -54,20 +48,7 @@ class MapStageComponent extends React.Component { updateScale(e) { e.preventDefault(); - const mousePointsTo = { - x: this.state.mouseX / this.props.mapScale - this.props.mapPosition.x / this.props.mapScale, - y: this.state.mouseY / this.props.mapScale - this.props.mapPosition.y / this.props.mapScale, - }; - const newScale = e.deltaY < 0 ? - this.props.mapScale * MAP_SCALE_PER_EVENT : - this.props.mapScale / MAP_SCALE_PER_EVENT; - const boundedScale = Math.min(Math.max(MAP_MIN_SCALE, newScale), MAP_MAX_SCALE); - - const newX = -(mousePointsTo.x - this.state.mouseX / boundedScale) * boundedScale; - const newY = -(mousePointsTo.y - this.state.mouseY / boundedScale) * boundedScale; - - this.setPositionWithBoundsCheck(newX, newY); - this.props.setMapScale(boundedScale); + this.props.zoomInOnPosition(e.deltaY < 0, this.state.mouseX, this.state.mouseY); } updateMousePosition() { @@ -95,26 +76,16 @@ class MapStageComponent extends React.Component { } moveWithDelta(deltaX, deltaY) { - this.setPositionWithBoundsCheck(this.props.mapPosition.x + deltaX, this.props.mapPosition.y + deltaY); - } - - setPositionWithBoundsCheck(newX, newY) { - const scaledMapSize = MAP_SIZE_IN_PIXELS * this.props.mapScale; - const updatedX = newX > 0 ? 0 : - (newX < -scaledMapSize + this.props.mapDimensions.width - ? -scaledMapSize + this.props.mapDimensions.width : newX); - const updatedY = newY > 0 ? 0 : - (newY < -scaledMapSize + this.props.mapDimensions.height - ? -scaledMapSize + this.props.mapDimensions.height : newY); - - this.props.setMapPosition(updatedX, updatedY); + this.props.setMapPositionWithBoundsCheck(this.props.mapPosition.x + deltaX, this.props.mapPosition.y + deltaY); } render() { return ( {this.stage = stage;}} + ref={(stage) => { + this.stage = stage; + }} width={this.props.mapDimensions.width} height={this.props.mapDimensions.height} onMouseMove={this.updateMousePosition.bind(this)} diff --git a/src/components/app/map/controls/ZoomControlComponent.js b/src/components/app/map/controls/ZoomControlComponent.js index c5628d16..8406e8c1 100644 --- a/src/components/app/map/controls/ZoomControlComponent.js +++ b/src/components/app/map/controls/ZoomControlComponent.js @@ -1,26 +1,19 @@ import React from "react"; -import {MAP_MAX_SCALE, MAP_MIN_SCALE, MAP_SCALE_PER_EVENT} from "../MapConstants"; - -const ZoomControlComponent = ({mapScale, setMapScale}) => { - const zoom = (out) => { - const newScale = out ? mapScale / MAP_SCALE_PER_EVENT : mapScale * MAP_SCALE_PER_EVENT; - const boundedScale = Math.min(Math.max(MAP_MIN_SCALE, newScale), MAP_MAX_SCALE); - setMapScale(boundedScale); - }; +const ZoomControlComponent = ({zoomInOnCenter}) => { return ( diff --git a/src/containers/app/map/MapStage.js b/src/containers/app/map/MapStage.js index e0c85651..32bde27c 100644 --- a/src/containers/app/map/MapStage.js +++ b/src/containers/app/map/MapStage.js @@ -1,20 +1,19 @@ import {connect} from "react-redux"; -import {setMapDimensions, setMapPosition, setMapScale} from "../../../actions/map"; +import {setMapDimensions, setMapPositionWithBoundsCheck, zoomInOnPosition} from "../../../actions/map"; import MapStageComponent from "../../../components/app/map/MapStageComponent"; const mapStateToProps = state => { return { mapPosition: state.map.position, mapDimensions: state.map.dimensions, - mapScale: state.map.scale, }; }; const mapDispatchToProps = dispatch => { return { - setMapPosition: (x, y) => dispatch(setMapPosition(x, y)), + zoomInOnPosition: (zoomIn, x, y) => dispatch(zoomInOnPosition(zoomIn, x, y)), + setMapPositionWithBoundsCheck: (x, y) => dispatch(setMapPositionWithBoundsCheck(x, y)), setMapDimensions: (width, height) => dispatch(setMapDimensions(width, height)), - setMapScale: (scale) => dispatch(setMapScale(scale)), }; }; diff --git a/src/containers/app/map/controls/ZoomControlContainer.js b/src/containers/app/map/controls/ZoomControlContainer.js index b9cf0a63..fd0e7563 100644 --- a/src/containers/app/map/controls/ZoomControlContainer.js +++ b/src/containers/app/map/controls/ZoomControlContainer.js @@ -1,5 +1,5 @@ import {connect} from "react-redux"; -import {setMapScale} from "../../../../actions/map"; +import {zoomInOnCenter} from "../../../../actions/map"; import ZoomControlComponent from "../../../../components/app/map/controls/ZoomControlComponent"; const mapStateToProps = state => { @@ -10,7 +10,7 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { - setMapScale: scale => dispatch(setMapScale(scale)), + zoomInOnCenter: zoomIn => dispatch(zoomInOnCenter(zoomIn)), }; }; -- cgit v1.2.3