react-planner-viewer
Version:
react-planner-viewer is a React Component for view plans builded with react-planner in 2D mode
142 lines (110 loc) • 4 kB
JavaScript
import {
BEGIN_DRAGGING_VERTEX,
UPDATE_DRAGGING_VERTEX,
END_DRAGGING_VERTEX,
MODE_DRAGGING_VERTEX,
MODE_IDLE
} from '../constants'
import {Map, List} from 'immutable';
import {sceneSnapElements} from '../utils/snap-scene';
import {nearestSnap} from '../utils/snap';
import {
detectAndUpdateAreas,
removeLine,
addLineAvoidingIntersections,
mergeEqualsVertices
} from '../utils/layer-operations';
import {orderVertices, pointsDistance, samePoints} from "../utils/geometry";
export default function (state, action) {
switch (action.type) {
case BEGIN_DRAGGING_VERTEX:
return beginDraggingVertex(state, action.layerID, action.vertexID, action.x, action.y);
case UPDATE_DRAGGING_VERTEX:
return updateDraggingVertex(state, action.x, action.y);
case END_DRAGGING_VERTEX:
return endDraggingVertex(state, action.x, action.y);
default:
return state;
}
}
function beginDraggingVertex(state, layerID, vertexID, x, y) {
let snapElements = sceneSnapElements(state.scene, new List(), state.snapMask);
return state.merge({
mode: MODE_DRAGGING_VERTEX,
snapElements,
draggingSupport: Map({
layerID, vertexID
})
});
}
function updateDraggingVertex(state, x, y) {
let {draggingSupport, snapElements, scene} = state;
let snap = null;
if (state.snapMask && !state.snapMask.isEmpty()) {
snap = nearestSnap(snapElements, x, y, state.snapMask);
if (snap) ({x, y} = snap.point);
}
let layerID = draggingSupport.get('layerID');
let vertexID = draggingSupport.get('vertexID');
return state.merge({
activeSnapElement: snap ? snap.snap : null,
scene: scene.mergeIn(['layers', layerID, 'vertices', vertexID], {x, y})
});
}
function endDraggingVertex(state, x, y) {
let catalog = state.catalog;
let {draggingSupport} = state;
let layerID = draggingSupport.get('layerID');
let vertexID = draggingSupport.get('vertexID');
let lineIDs = state.scene.layers.get(layerID).vertices.get(vertexID).lines;
let scene = state.scene.updateIn(['layers', layerID], layer => layer.withMutations(layer => {
lineIDs.forEach(lineID => {
let line = layer.lines.get(lineID);
if (line) {
let oldVertexID;
if (line.vertices.get(0) === vertexID) {
// I need to invert vertices
oldVertexID = line.vertices.get(1);
} else {
oldVertexID = line.vertices.get(0);
}
let oldVertex = layer.vertices.get(oldVertexID);
let vertex = layer.vertices.get(vertexID);
let oldHoles = [];
let orderedVertices = orderVertices([oldVertex, vertex]);
line.holes.forEach(holeID => {
let hole = layer.holes.get(holeID);
let oldLineLength = pointsDistance(oldVertex.x, oldVertex.y, vertex.x, vertex.y);
let alpha = Math.atan2(orderedVertices[1].y - orderedVertices[0].y,
orderedVertices[1].x - orderedVertices[0].x);
let offset = hole.offset;
if (orderedVertices[1].x === line.vertices.get(1).x
&& orderedVertices[1].y === line.vertices(1).y) {
offset = 1 - offset;
}
let xp = oldLineLength * offset * Math.cos(alpha) + orderedVertices[0].x;
let yp = oldLineLength * offset * Math.sin(alpha) + orderedVertices[0].y;
oldHoles.push({hole, offsetPosition: {x: xp, y: yp}});
});
mergeEqualsVertices(layer, vertexID);
removeLine(layer, lineID);
if (!samePoints(oldVertex, vertex)) {
addLineAvoidingIntersections(layer, line.type,
oldVertex.x, oldVertex.y,
vertex.x, vertex.y,
catalog,
line.properties, oldHoles);
}
}
});
detectAndUpdateAreas(layer, catalog);
}));
return state.merge({
mode: MODE_IDLE,
draggingSupport: null,
scene,
activeSnapElement: null,
snapElements: new List(),
sceneHistory: state.sceneHistory.push(scene)
});
}