Skip to content

Commit e3b08d0

Browse files
authored
Merge pull request #44 from tbolis/feature/remove-selection
Feature/remove selection
2 parents 32264b3 + 33b4e70 commit e3b08d0

File tree

13 files changed

+452
-364
lines changed

13 files changed

+452
-364
lines changed

examples/main.jsx

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@ import color from '@material-ui/core/colors/blueGrey';
2828

2929
import UndoIcon from '@material-ui/icons/Undo';
3030
import RedoIcon from '@material-ui/icons/Redo';
31-
import ClearIcon from '@material-ui/icons/Delete';
31+
import DeleteIcon from '@material-ui/icons/Delete';
3232
import SaveIcon from '@material-ui/icons/Save';
33-
import RemoveIcon from '@material-ui/icons/Clear';
33+
import ClearIcon from '@material-ui/icons/Clear';
3434
import DownloadIcon from '@material-ui/icons/CloudDownload';
3535
import ZoomInIcon from '@material-ui/icons/ZoomIn';
3636
import ZoomOutIcon from '@material-ui/icons/ZoomOut';
37+
import RemoveIcon from '@material-ui/icons/Remove';
3738
import dataJson from './data.json';
3839
import dataJsonControlled from './data.json.controlled';
3940
import {SketchField, Tools} from '../src';
@@ -124,6 +125,7 @@ class SketchFieldDemo extends React.Component {
124125
shadowWidth: 0,
125126
shadowOffset: 0,
126127
tool: Tools.Pencil,
128+
enableRemoveSelected: false,
127129
fillWithColor: false,
128130
fillWithBackgroundColor: false,
129131
drawings: [],
@@ -146,7 +148,12 @@ class SketchFieldDemo extends React.Component {
146148
};
147149
}
148150

149-
_selectTool = event => this.setState({ tool: event.target.value });
151+
_selectTool = event => {
152+
this.setState({
153+
tool: event.target.value,
154+
enableRemoveSelected: event.target.value === Tools.Select
155+
});
156+
};
150157

151158
_save = () => {
152159
let drawings = this.state.drawings;
@@ -181,7 +188,7 @@ class SketchFieldDemo extends React.Component {
181188
style={styles.gridTile}
182189
actionIcon={
183190
<IconButton onTouchTap={c => this._removeMe(index)}>
184-
<RemoveIcon color="white"/>
191+
<ClearIcon color="white"/>
185192
</IconButton>
186193
}>
187194
<img src={drawing}/>
@@ -223,6 +230,10 @@ class SketchFieldDemo extends React.Component {
223230
});
224231
};
225232

233+
_removeSelected = () => {
234+
this._sketch.removeSelected()
235+
};
236+
226237
_onSketchChange = () => {
227238
let prev = this.state.canUndo;
228239
let now = this._sketch.canUndo();
@@ -278,6 +289,9 @@ class SketchFieldDemo extends React.Component {
278289
render = () => {
279290
let { controlledValue } = this.state;
280291
const theme = createMuiTheme({
292+
typography: {
293+
useNextVariants: true,
294+
},
281295
palette: {
282296
primary: { main: color[500] }, // Purple and green play nicely together.
283297
secondary: { main: '#11cb5f' }, // This is just green.A700 as hex.
@@ -315,7 +329,7 @@ class SketchFieldDemo extends React.Component {
315329
<IconButton
316330
color="primary"
317331
onClick={this._clear}>
318-
<ClearIcon/>
332+
<DeleteIcon/>
319333
</IconButton>
320334
</Toolbar>
321335
</AppBar>
@@ -365,19 +379,31 @@ class SketchFieldDemo extends React.Component {
365379
}/>
366380
<Collapse in={this.state.expandTools}>
367381
<CardContent>
368-
<TextField
369-
select={true}
370-
label="Canvas Tool"
371-
value={this.state.tool}
372-
onChange={this._selectTool}
373-
helperText="Please select Canvas Tool">
374-
<MenuItem value={Tools.Select} key="Select">Select</MenuItem>
375-
<MenuItem value={Tools.Pencil} key="Pencil">Pencil</MenuItem>
376-
<MenuItem value={Tools.Line} key="Line">Line</MenuItem>
377-
<MenuItem value={Tools.Rectangle} key="Rectangle">Rectangle</MenuItem>
378-
<MenuItem value={Tools.Circle} key="Circle">Circle</MenuItem>
379-
<MenuItem value={Tools.Pan} key="Pan">Pan</MenuItem>
380-
</TextField>
382+
<div className="row">
383+
<div className="col">
384+
<TextField
385+
select={true}
386+
label="Canvas Tool"
387+
value={this.state.tool}
388+
onChange={this._selectTool}
389+
helperText="Please select Canvas Tool">
390+
<MenuItem value={Tools.Select} key="Select">Select</MenuItem>
391+
<MenuItem value={Tools.Pencil} key="Pencil">Pencil</MenuItem>
392+
<MenuItem value={Tools.Line} key="Line">Line</MenuItem>
393+
<MenuItem value={Tools.Rectangle} key="Rectangle">Rectangle</MenuItem>
394+
<MenuItem value={Tools.Circle} key="Circle">Circle</MenuItem>
395+
<MenuItem value={Tools.Pan} key="Pan">Pan</MenuItem>
396+
</TextField>
397+
</div>
398+
<div className="col">
399+
<IconButton
400+
color="primary"
401+
disabled={!this.state.enableRemoveSelected}
402+
onClick={this._removeSelected}>
403+
<DeleteIcon/>
404+
</IconButton>
405+
</div>
406+
</div>
381407
<br/>
382408
<br/>
383409
<Typography id="slider">Line Weight</Typography>
@@ -544,8 +570,8 @@ class SketchFieldDemo extends React.Component {
544570
<CardContent>
545571
<div>
546572
<TextField
547-
floatingLabelText='Image URL'
548-
hintText='Copy/Paste an image URL'
573+
label='Image URL'
574+
helperText='Copy/Paste an image URL'
549575
onChange={(e) => this.setState({ imageUrl: e.target.value })}
550576
value={this.state.imageUrl}/>
551577
<Button

src/SketchField.jsx

Lines changed: 84 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,17 @@ class SketchField extends PureComponent {
4545
widthCorrection: PropTypes.number,
4646
// Specify some height correction which will be applied on auto resize
4747
heightCorrection: PropTypes.number,
48-
48+
// Specify action on change
4949
onChange: PropTypes.func,
50+
// Default initial value
5051
defaultValue: PropTypes.object,
52+
// Sketch width
5153
width: PropTypes.number,
54+
// Sketch height
5255
height: PropTypes.number,
53-
className: PropTypes.object,
56+
// Class name to pass to container div of canvas
57+
className: PropTypes.string,
58+
// Style options to pass to container div of canvas
5459
style: PropTypes.object,
5560
};
5661

@@ -139,10 +144,10 @@ class SketchField extends PureComponent {
139144
return
140145
}
141146
let obj = e.target;
142-
obj.version = 1;
147+
obj.__version = 1;
143148
// record current object state as json and save as originalState
144149
let objState = obj.toJSON();
145-
obj.originalState = objState;
150+
obj.__originalState = objState;
146151
let state = JSON.stringify(objState);
147152
// object, previous state, current state
148153
this._history.keep([obj, state, state])
@@ -169,12 +174,27 @@ class SketchField extends PureComponent {
169174

170175
};
171176

177+
_onObjectModified = (e) => {
178+
let obj = e.target;
179+
obj.__version += 1;
180+
let prevState = JSON.stringify(obj.__originalState);
181+
let objState = obj.toJSON();
182+
// record current object state as json and update to originalState
183+
obj.__originalState = objState;
184+
let currState = JSON.stringify(objState);
185+
this._history.keep([obj, prevState, currState]);
186+
};
187+
172188
/**
173189
* Action when an object is removed from the canvas
174190
*/
175191
_onObjectRemoved = (e) => {
176192
let obj = e.target;
177-
obj.version = 0;
193+
if (obj.__removed) {
194+
obj.__version += 1;
195+
return
196+
}
197+
obj.__version = 0;
178198
};
179199

180200
/**
@@ -204,6 +224,27 @@ class SketchField extends PureComponent {
204224
}
205225
};
206226

227+
_onMouseUp = (e) => {
228+
this._selectedTool.doMouseUp(e);
229+
// Update the final state to new-generated object
230+
// Ignore Path object since it would be created after mouseUp
231+
// Assumed the last object in canvas.getObjects() in the newest object
232+
if (this.props.tool !== Tool.Pencil) {
233+
const canvas = this._fc;
234+
const objects = canvas.getObjects();
235+
const newObj = objects[objects.length - 1];
236+
if (newObj && newObj.__version === 1) {
237+
newObj.__originalState = newObj.toJSON();
238+
}
239+
}
240+
if (this.props.onChange) {
241+
let onChange = this.props.onChange;
242+
setTimeout(() => {
243+
onChange(e.e)
244+
}, 10)
245+
}
246+
};
247+
207248
/**
208249
* Track the resize of the window and update our state
209250
*
@@ -290,12 +331,18 @@ class SketchField extends PureComponent {
290331
let history = this._history;
291332
let [obj, prevState, currState] = history.getCurrent();
292333
history.undo();
293-
if (obj.version === 1) {
334+
if (obj.__removed) {
335+
this.setState({ action: false }, () => {
336+
this._fc.add(obj);
337+
obj.__version -= 1;
338+
obj.__removed = false;
339+
});
340+
} else if (obj.__version <= 1) {
294341
this._fc.remove(obj);
295342
} else {
343+
obj.__version -= 1;
296344
obj.setOptions(JSON.parse(prevState));
297345
obj.setCoords();
298-
obj.version -= 1;
299346
this._fc.renderAll()
300347
}
301348
if (this.props.onChange) {
@@ -306,20 +353,19 @@ class SketchField extends PureComponent {
306353
/**
307354
* Perform a redo operation on canvas, if it cannot redo it will leave the canvas intact
308355
*/
309-
310356
redo = () => {
311357
let history = this._history;
312358
if (history.canRedo()) {
313359
let canvas = this._fc;
314360
//noinspection Eslint
315361
let [obj, prevState, currState] = history.redo();
316-
if (obj.version === 0) {
362+
if (obj.__version === 0) {
317363
this.setState({ action: false }, () => {
318364
canvas.add(obj);
319-
obj.version = 1
365+
obj.__version = 1
320366
})
321367
} else {
322-
obj.version += 1;
368+
obj.__version += 1;
323369
obj.setOptions(JSON.parse(currState))
324370
}
325371
obj.setCoords();
@@ -410,6 +456,33 @@ class SketchField extends PureComponent {
410456
this._history.clear();
411457
return discarded
412458
};
459+
460+
/**
461+
* Remove selected object from the canvas
462+
*/
463+
removeSelected = () => {
464+
let canvas = this._fc;
465+
let activeObj = canvas.getActiveObject();
466+
if (activeObj) {
467+
let selected = [];
468+
if (activeObj.type === 'activeSelection') {
469+
activeObj.forEachObject((obj) => [].push(obj));
470+
} else {
471+
selected.push(activeObj)
472+
}
473+
selected.forEach(obj => {
474+
obj.__removed = true;
475+
let objState = obj.toJSON();
476+
obj.__originalState = objState;
477+
let state = JSON.stringify(objState);
478+
this._history.keep([obj, state, state]);
479+
canvas.remove(obj);
480+
});
481+
canvas.discardActiveObject();
482+
canvas.requestRenderAll();
483+
}
484+
};
485+
413486
/**
414487
* Sets the background from the dataUrl given
415488
*
@@ -517,38 +590,6 @@ class SketchField extends PureComponent {
517590
}
518591
};
519592

520-
_onObjectModified = (e) => {
521-
let obj = e.target;
522-
obj.version += 1;
523-
let prevState = JSON.stringify(obj.originalState);
524-
let objState = obj.toJSON();
525-
// record current object state as json and update to originalState
526-
obj.originalState = objState;
527-
let currState = JSON.stringify(objState);
528-
this._history.keep([obj, prevState, currState]);
529-
};
530-
531-
_onMouseUp = (e) => {
532-
this._selectedTool.doMouseUp(e);
533-
// Update the final state to new-generated object
534-
// Ignore Path object since it would be created after mouseUp
535-
// Assumed the last object in canvas.getObjects() in the newest object
536-
if (this.props.tool !== Tool.Pencil) {
537-
const canvas = this._fc;
538-
const objects = canvas.getObjects();
539-
const newObj = objects[objects.length - 1];
540-
if (newObj && newObj.version === 1) {
541-
newObj.originalState = newObj.toJSON();
542-
}
543-
}
544-
if (this.props.onChange) {
545-
let onChange = this.props.onChange;
546-
setTimeout(() => {
547-
onChange(e.e)
548-
}, 10)
549-
}
550-
};
551-
552593
render = () => {
553594
let {
554595
className,

0 commit comments

Comments
 (0)