UNPKG

react-floorplanner

Version:

react-floorplanner is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.

219 lines (174 loc) 5.72 kB
import {List, Map} from 'immutable'; import { SELECT_TOOL_DRAWING_ITEM, UPDATE_DRAWING_ITEM, END_DRAWING_ITEM, BEGIN_DRAGGING_ITEM, UPDATE_DRAGGING_ITEM, END_DRAGGING_ITEM, BEGIN_ROTATING_ITEM, UPDATE_ROTATING_ITEM, END_ROTATING_ITEM, SELECT_ITEM, MODE_IDLE, MODE_DRAWING_ITEM, MODE_DRAGGING_ITEM, MODE_ROTATING_ITEM } from '../constants'; import {addItem, removeItem, unselect, select, unselectAll} from '../utils/layer-operations'; import * as Geometry from '../utils/geometry'; export default function (state, action) { switch (action.type) { case SELECT_ITEM: return selectItem(state, action.layerID, action.itemID); case SELECT_TOOL_DRAWING_ITEM: return selectToolDrawingItem(state, action.sceneComponentType); case UPDATE_DRAWING_ITEM: return updateDrawingItem(state, action.layerID, action.x, action.y); case END_DRAWING_ITEM: return endDrawingItem(state, action.layerID, action.x, action.y); case BEGIN_DRAGGING_ITEM: return beginDraggingItem(state, action.layerID, action.itemID, action.x, action.y); case UPDATE_DRAGGING_ITEM: return updateDraggingItem(state, action.x, action.y); case END_DRAGGING_ITEM: return endDraggingItem(state, action.x, action.y); case BEGIN_ROTATING_ITEM: return beginRotatingItem(state, action.layerID, action.itemID, action.x, action.y); case UPDATE_ROTATING_ITEM: return updateRotatingItem(state, action.x, action.y); case END_ROTATING_ITEM: return endRotatingItem(state, action.x, action.y); default: return state; } } function selectToolDrawingItem(state, sceneComponentType) { return state.merge({ mode: MODE_DRAWING_ITEM, drawingSupport: Map({ type: sceneComponentType }) }); } /** holes operations **/ function updateDrawingItem(state, layerID, x, y) { let {drawingSupport, catalog} = state; let scene = state.scene.updateIn(['layers', layerID], layer => layer.withMutations(layer => { if (drawingSupport.has('currentID')) { layer.updateIn(['items', drawingSupport.get('currentID')], item => item.merge({x, y})); } else { let {item} = addItem(layer, drawingSupport.get('type'), x, y, 200, 100, 0, catalog); select(layer, 'items', item.id); drawingSupport = drawingSupport.set('currentID', item.id); } })); return state.merge({ scene, drawingSupport }); } function endDrawingItem(state, layerID, x, y) { let catalog = state.catalog; state = updateDrawingItem(state, layerID, x, y, catalog); let scene = state.scene.updateIn(['layers', layerID], layer => unselectAll(layer)); return state.merge({ scene, sceneHistory: state.sceneHistory.push(scene), drawingSupport: Map({ type: state.drawingSupport.get('type') }) }); } function beginDraggingItem(state, layerID, itemID, x, y) { let item = state.getIn(['scene', 'layers', layerID, 'items', itemID]); return state.merge({ mode: MODE_DRAGGING_ITEM, draggingSupport: Map({ layerID, itemID, startPointX: x, startPointY: y, originalX: item.x, originalY: item.y }) }); } function updateDraggingItem(state, x, y) { let {draggingSupport, scene} = state; let layerID = draggingSupport.get('layerID'); let itemID = draggingSupport.get('itemID'); let startPointX = draggingSupport.get('startPointX'); let startPointY = draggingSupport.get('startPointY'); let originalX = draggingSupport.get('originalX'); let originalY = draggingSupport.get('originalY'); let diffX = startPointX - x; let diffY = startPointY - y; let item = scene.getIn(['layers', layerID, 'items', itemID]); item = item.merge({ x: originalX - diffX, y: originalY - diffY }); return state.merge({ scene: scene.mergeIn(['layers', layerID, 'items', itemID], item) }); } function endDraggingItem(state, x, y) { state = updateDraggingItem(state, x, y); return state.merge({ mode: MODE_IDLE, sceneHistory: state.sceneHistory.push(state.scene) }); } function beginRotatingItem(state, layerID, itemID, x, y) { let item = state.getIn(['scene', 'layers', layerID, 'items', itemID]); return state.merge({ mode: MODE_ROTATING_ITEM, rotatingSupport: Map({ layerID, itemID }) }); } function updateRotatingItem(state, x, y) { let {rotatingSupport, scene} = state; let layerID = rotatingSupport.get('layerID'); let itemID = rotatingSupport.get('itemID'); let item = state.getIn(['scene', 'layers', layerID, 'items', itemID]); let deltaX = x - item.x; let deltaY = y - item.y; let rotation = Math.atan2(deltaY, deltaX) * 180 / Math.PI - 90; if (-5 < rotation && rotation < 5) rotation = 0; if (-95 < rotation && rotation < -85) rotation = -90; if (-185 < rotation && rotation < -175) rotation = -180; if (85 < rotation && rotation < 90) rotation = 90; if (-270 < rotation && rotation < -265) rotation = 90; item = item.merge({ rotation, }); return state.merge({ scene: scene.mergeIn(['layers', layerID, 'items', itemID], item) }); } function endRotatingItem(state, x, y) { state = updateRotatingItem(state, x, y); return state.merge({ mode: MODE_IDLE, sceneHistory: state.sceneHistory.push(state.scene) }); } function selectItem(state, layerID, itemID) { let scene = state.scene; scene = scene.merge({ layers: scene.layers.map(unselectAll), selectedLayer: layerID }); scene = scene.updateIn(['layers', layerID], layer => layer.withMutations(layer => { select(layer, 'items', itemID); }) ); return state.merge({ scene, sceneHistory: state.sceneHistory.push(scene) }) }