diff options
Diffstat (limited to 'opendc-web/opendc-web-ui/src/store/middlewares')
| -rw-r--r-- | opendc-web/opendc-web-ui/src/store/middlewares/dummy-middleware.js | 3 | ||||
| -rw-r--r-- | opendc-web/opendc-web-ui/src/store/middlewares/viewport-adjustment.js | 73 |
2 files changed, 76 insertions, 0 deletions
diff --git a/opendc-web/opendc-web-ui/src/store/middlewares/dummy-middleware.js b/opendc-web/opendc-web-ui/src/store/middlewares/dummy-middleware.js new file mode 100644 index 00000000..5ba35691 --- /dev/null +++ b/opendc-web/opendc-web-ui/src/store/middlewares/dummy-middleware.js @@ -0,0 +1,3 @@ +export const dummyMiddleware = (store) => (next) => (action) => { + next(action) +} diff --git a/opendc-web/opendc-web-ui/src/store/middlewares/viewport-adjustment.js b/opendc-web/opendc-web-ui/src/store/middlewares/viewport-adjustment.js new file mode 100644 index 00000000..b4472c54 --- /dev/null +++ b/opendc-web/opendc-web-ui/src/store/middlewares/viewport-adjustment.js @@ -0,0 +1,73 @@ +import { SET_MAP_DIMENSIONS, setMapPosition, setMapScale } from '../../actions/map' +import { SET_CURRENT_TOPOLOGY } from '../../actions/topology/building' +import { + MAP_MAX_SCALE, + MAP_MIN_SCALE, + SIDEBAR_WIDTH, + TILE_SIZE_IN_PIXELS, + VIEWPORT_PADDING, +} from '../../components/app/map/MapConstants' +import { calculateRoomListBounds } from '../../util/tile-calculations' + +export const viewportAdjustmentMiddleware = (store) => (next) => (action) => { + const state = store.getState() + + let topologyId = '-1' + let mapDimensions = {} + if (action.type === SET_CURRENT_TOPOLOGY && action.topologyId !== '-1') { + topologyId = action.topologyId + mapDimensions = state.map.dimensions + } else if (action.type === SET_MAP_DIMENSIONS && state.currentTopologyId !== '-1') { + topologyId = state.currentTopologyId + mapDimensions = { width: action.width, height: action.height } + } + + if (topologyId !== '-1') { + const roomIds = state.objects.topology[topologyId].roomIds + const rooms = roomIds.map((id) => Object.assign({}, state.objects.room[id])) + rooms.forEach((room) => (room.tiles = room.tileIds.map((tileId) => state.objects.tile[tileId]))) + + let hasNoTiles = true + for (let i in rooms) { + if (rooms[i].tiles.length > 0) { + hasNoTiles = false + break + } + } + + if (!hasNoTiles) { + const viewportParams = calculateParametersToZoomInOnRooms(rooms, mapDimensions.width, mapDimensions.height) + store.dispatch(setMapPosition(viewportParams.newX, viewportParams.newY)) + store.dispatch(setMapScale(viewportParams.newScale)) + } + } + + next(action) +} + +function calculateParametersToZoomInOnRooms(rooms, mapWidth, mapHeight) { + const bounds = calculateRoomListBounds(rooms) + const newScale = calculateNewScale(bounds, mapWidth, mapHeight) + + // Coordinates of the center of the room, relative to the global origin of the map + const roomCenterCoordinates = { + x: bounds.center.x * TILE_SIZE_IN_PIXELS * newScale, + y: bounds.center.y * TILE_SIZE_IN_PIXELS * newScale, + } + + const newX = -roomCenterCoordinates.x + mapWidth / 2 + const newY = -roomCenterCoordinates.y + mapHeight / 2 + + return { newScale, newX, newY } +} + +function calculateNewScale(bounds, mapWidth, mapHeight) { + const width = bounds.max.x - bounds.min.x + const height = bounds.max.y - bounds.min.y + + const scaleX = (mapWidth - 2 * SIDEBAR_WIDTH) / (width * TILE_SIZE_IN_PIXELS + 2 * VIEWPORT_PADDING) + const scaleY = mapHeight / (height * TILE_SIZE_IN_PIXELS + 2 * VIEWPORT_PADDING) + const newScale = Math.min(scaleX, scaleY) + + return Math.min(Math.max(MAP_MIN_SCALE, newScale), MAP_MAX_SCALE) +} |
