roiact
Version:
299 lines (240 loc) • 11.2 kB
JavaScript
;
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _reactRedux = require("react-redux");
var _semanticUiReact = require("semantic-ui-react");
var _SketchModule = _interopRequireDefault(require("./Sketch.module.scss"));
var _reactSizeme = require("react-sizeme");
var _Canvas = _interopRequireDefault(require("../../Redux/Canvas"));
var _EventDispatcher = _interopRequireDefault(require("../../Services/EventDispatcher"));
require("fabric");
var _Canvas2 = _interopRequireDefault(require("./Canvas"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
//} from "../../node_modules/fabric/dist/fabric.js";
// OK, this is local state, something like instance properties for a class
// component but for a pure functional component. It's useful because I want this state
// to persist among new renders, and I don't want to use the react state because I want
// the changes to be applied immediately. I'll take care of resetting it if needed.
// Also this component is a pure logical component, and full of listeners callbacks.
// Such functions, when registered, won't receive updates for the redux props that change,
// so I'll use this object reference inside them, and I'll update this object properties
// when a redux prop I need inside those functions changes.
var initLocalState = function initLocalState() {
return {
canvas: null,
canvasSize: null,
ignoreSelectionCreated: false
};
};
var s = initLocalState();
/**
* The sketch component, the mind behind the drawing feature
* EventDispatcher is used to communicate ina sync way between
* different components
*/
var Sketch = function Sketch(props) {
// redux store stuff
var dispatch = (0, _reactRedux.useDispatch)();
var tools = (0, _reactRedux.useSelector)(function (state) {
return state.canvas.tools;
});
var shapes = (0, _reactRedux.useSelector)(function (state) {
return state.canvas.shapes;
});
if (s.canvas) {
s.canvas.setStoreShapes(shapes);
s.canvas.setShapeMode(tools.mode);
s.canvas.setShapeThreshold(50);
}
var save = (0, _react.useCallback)(function (evtName, mshapes) {
dispatch(_Canvas.default.setSaving(true));
props.save_callback(mshapes);
/*request(
'saveNoTrespassingZones',
[shapes],
'Si è verificato un errore nel salvare le no trespassing zones: {error}',
response => {
dispatch(CanvasActions.setSaving(false))
dispatch(CanvasActions.setDirty(false))
toast(
'Salvataggio effettuato con successo',
{ type: 'success' }
)
},
error => { // eslint-disable-line
dispatch(CanvasActions.setSaving(false))
}
)*/
dispatch(_Canvas.default.setSaving(false));
}, []); // listeners callbacks
// shape removal: notified by the objects list
var handleShapeRemoval = (0, _react.useCallback)(function (evtName, id) {
return s.canvas.removeShape(id);
}, []); // shape selection: notified by the objects list
var handleShapeSelection = (0, _react.useCallback)(function (evtName, ids, from) {
if (from !== 'canvas') {
// also from the canvas we trigger this event and we don't need to process it
// avoid ping pong between this component and objects component
s.ignoreSelectionCreated = true;
s.canvas.setActiveSelection(ids[0]);
}
}); // shape selection: notify the objects list
var handleSelectionCreation = (0, _react.useCallback)(function (e) {
if (!s.ignoreSelectionCreated) {
_EventDispatcher.default.emit('shapeSelected', e.selected.map(function (st) {
st.lockScalingFlip = true;
st.lockRotation = true;
st.lockMovementX = true;
st.lockMovementY = true;
st.lockScalingX = true;
st.lockScalingY = true;
return st.id;
}), 'canvas');
}
s.ignoreSelectionCreated = false;
}, []); // shape selection updated: notify the objects list
var handleSelectionUpdate = (0, _react.useCallback)(function (e) {
if (!s.ignoreSelectionCreated) {
e.target.lockScalingFlip = true;
e.target.lockRotation = true;
e.target.lockMovementX = true;
e.target.lockMovementY = true;
e.target.lockScalingX = true;
e.target.lockScalingY = true;
_EventDispatcher.default.emit('shapeSelected', [e.target.id], 'canvas');
}
s.ignoreSelectionCreated = false;
}, []); // shape selection cleared: notify the objects list
var handleSelectionClear = (0, _react.useCallback)(function (e) {
_EventDispatcher.default.emit('shapeSelected', null, 'canvas');
}, []); // shape edit -> save to redux store
var handleShapeEdit = (0, _react.useCallback)(function (e) {
dispatch(_Canvas.default.editShape({
id: e.target.id,
shape: s.canvas.fabric2redux(e.target)
}));
}, []);
var handleShapeRemove = (0, _react.useCallback)(function (id) {
dispatch(_Canvas.default.removeShape(id));
}, []); // DID MOUNT
(0, _react.useEffect)(function () {
console.info('SKETCH', 'mounting');
dispatch(_Canvas.default.initShapes(props.shapes));
s.canvas = new _Canvas2.default('canvas', {
opacity: tools.opacity,
onShapeRemove: handleShapeRemove,
setDrawing: function setDrawing(isDrawing) {
return dispatch(_Canvas.default.setDrawing(isDrawing));
}
});
s.canvas.setStoreShapes(shapes);
addListeners(); // register all listeners
// when unmounting
return function () {
console.info('SKETCH', 'unmounting');
s.canvas.deinitialize();
removeListeners(); // clear all listeners
};
}, []); // fetch shapes
(0, _react.useEffect)(function () {
s.canvas.setStoreShapes(shapes);
s.canvas.redraw();
}, [shapes]); // resize
(0, _react.useEffect)(function () {
s.canvas.resize(props.size);
}, [props.size.width, props.size.height]); // update opacity
(0, _react.useEffect)(function () {
s.canvas.setOpacity(tools.opacity);
}, [tools.opacity]); // on selected tool change
(0, _react.useEffect)(function () {
if (tools.selected) {
s.canvas.disableSelection(); // add mouse events (and remove prev)
s.canvas.removeMouseListeners();
s.canvas.addMouseListeners(mousedown, mousemove);
} else {
s.canvas.enableSelection();
s.canvas.removeMouseListeners();
}
}, [tools.selected]);
var addListeners = function addListeners() {
console.info('registering listeners'); // Tools dispatches
// I prefer to use a custom dispatcher to trigger events which seems more like
// native events than redux actions. I don't like to manage every syncronization
// with useEffect or componentDidMount because we always have to compare prev props
// with new props.
_EventDispatcher.default.register('save', save);
_EventDispatcher.default.register('shapeRemoved', handleShapeRemoval);
_EventDispatcher.default.register('shapeSelected', handleShapeSelection);
_EventDispatcher.default.register('redraw', function () {
s.canvas.redraw.bind(s.canvas);
}); // obeserve canvas selection.
s.canvas.addSelectionListeners(handleSelectionCreation, handleSelectionUpdate, handleSelectionClear); // shape modification
s.canvas.addShapeUpdateListener(handleShapeEdit);
};
var removeListeners = function removeListeners() {
_EventDispatcher.default.unregister('shapeRemoved', handleShapeRemoval);
_EventDispatcher.default.unregister('shapeSelected', handleShapeSelection);
_EventDispatcher.default.unregister('redraw', s.canvas.redraw);
s.canvas.removeSelectionListeners();
s.canvas.removeShapeUpdateListener();
};
var mousedown = function mousedown(e) {
if (s.canvas.getActiveSelection() && !s.canvas.drawing || !tools.selected) {
return false;
}
dispatch(_Canvas.default.setDrawing(true));
s.canvas.drawShape(tools.selected, 'mousedown', e, handleDrawEnd);
};
var mousemove = function mousemove(e) {
if (s.canvas.getActiveSelection() && !s.canvas.isDrawing || !tools.selected) {
return false;
}
s.canvas.drawShape(tools.selected, 'mousemove', e, handleDrawEnd);
};
var handleDrawEnd = function handleDrawEnd(shape) {
dispatch(_Canvas.default.addShape({
id: shape.id,
name: shape.name,
type: shape.type,
mode: shape.mode,
threshold: shape.threshold,
data: s.canvas.fabric2redux(shape)
})); // notify the object list about selection
_EventDispatcher.default.emit('shapeSelected', [shape.id], 'canvas');
};
return /*#__PURE__*/_react.default.createElement("div", {
className: _SketchModule.default.canvasWrapper
}, /*#__PURE__*/_react.default.createElement(_semanticUiReact.Image, {
style: {
position: 'absolute',
width: '1080px',
height: '607px'
},
src: "".concat(props.photo)
}), /*#__PURE__*/_react.default.createElement("canvas", {
id: "canvas",
className: _SketchModule.default.canvas
}));
};
Sketch.propTypes = {
width: _propTypes.default.number,
height: _propTypes.default.number,
size: _propTypes.default.shape({
width: _propTypes.default.number,
height: _propTypes.default.number
}),
photo: _propTypes.default.string,
shapes: _propTypes.default.string,
save_callback: _propTypes.default.func
};
var _default = (0, _reactSizeme.withSize)({
monitorHeight: true
})(Sketch);
exports.default = _default;