redhotmagma-graphics-editor 1.26.5 → 1.27.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -5
- package/src/CanvasAdapters/PaperJs/Canvas.ts +2 -1
- package/src/CanvasAdapters/PaperJs/Objects/Text.ts +8 -1
- package/src/CanvasInterface/Canvas.ts +8 -1
- package/src/CanvasInterface/Objects/CanvasObject.ts +69 -5
- package/src/Components/Editor/Editor.js +3 -0
- package/src/Components/InlineToolbox/InlineToolbox.js +28 -14
- package/src/Components/SelectionToolbox/SelectionToolbox.js +54 -1
package/package.json
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redhotmagma-graphics-editor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.27.2",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"files": [
|
|
8
|
-
"
|
|
9
|
-
"CanvasInterface",
|
|
10
|
-
"Components",
|
|
11
|
-
"Utils",
|
|
8
|
+
"lib",
|
|
12
9
|
"src",
|
|
13
10
|
"scripts",
|
|
14
11
|
".babelrc"
|
|
@@ -88,6 +88,7 @@ export class Canvas extends AbstractCanvas {
|
|
|
88
88
|
this._view.center = new paper.Point(this._view.size.divide(2));
|
|
89
89
|
this._view.viewSize = size;
|
|
90
90
|
this._maskHandler && this._maskHandler.updateOutline();
|
|
91
|
+
this.updateObjectConstraints();
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
saveViewBox() {
|
|
@@ -174,7 +175,7 @@ export class Canvas extends AbstractCanvas {
|
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
onMouseDrag(event) {
|
|
177
|
-
if (this.selectedObject) {
|
|
178
|
+
if (this.selectedObject && !this.selectedObject.locked && !this.selectedObject.autoFit) {
|
|
178
179
|
const { x: dx, y: dy } = event.delta;
|
|
179
180
|
const o = this.selectedObject;
|
|
180
181
|
o.x += dx;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import debounce from 'lodash/debounce';
|
|
2
|
+
import isInteger from 'lodash/isInteger';
|
|
2
3
|
import { CanvasObject } from './CanvasObject';
|
|
3
4
|
import { TextInterface } from '../../../CanvasInterface/Objects/Text';
|
|
4
5
|
import { Logger } from '../../../Utils/Logger';
|
|
@@ -40,7 +41,10 @@ export class Text extends CanvasObject implements TextInterface {
|
|
|
40
41
|
const scaling = this.scaling;
|
|
41
42
|
if (scaling !== 1) {
|
|
42
43
|
this._scaling = 1;
|
|
43
|
-
|
|
44
|
+
const fontSize = Math.floor(this._fontSize * scaling);
|
|
45
|
+
if (isInteger(fontSize)) {
|
|
46
|
+
this.fontSize = fontSize;
|
|
47
|
+
}
|
|
44
48
|
}
|
|
45
49
|
}, 500);
|
|
46
50
|
|
|
@@ -86,6 +90,9 @@ export class Text extends CanvasObject implements TextInterface {
|
|
|
86
90
|
if (!fontSize) {
|
|
87
91
|
throw new Error('The given value is not a number!');
|
|
88
92
|
}
|
|
93
|
+
if (fontSize === this._fontSize) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
89
96
|
this._fontSize = Math.max(this._fontSizeMin, fontSize);
|
|
90
97
|
this.build();
|
|
91
98
|
this.triggerChangeEvent(prevState);
|
|
@@ -166,6 +166,12 @@ export abstract class AbstractCanvas {
|
|
|
166
166
|
return this;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
updateObjectConstraints(): void {
|
|
170
|
+
for (const o of this.objects) {
|
|
171
|
+
o.updateConstraints();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
169
175
|
update() {
|
|
170
176
|
return this;
|
|
171
177
|
}
|
|
@@ -198,9 +204,10 @@ export abstract class AbstractCanvas {
|
|
|
198
204
|
}
|
|
199
205
|
|
|
200
206
|
getState(): any {
|
|
201
|
-
const { selectedObject } = this;
|
|
207
|
+
const { selectedObject, size } = this;
|
|
202
208
|
return {
|
|
203
209
|
selectedObject: selectedObject ? selectedObject.getState() : null,
|
|
210
|
+
size,
|
|
204
211
|
};
|
|
205
212
|
}
|
|
206
213
|
|
|
@@ -32,7 +32,11 @@ export abstract class AbstractCanvasObject {
|
|
|
32
32
|
// technical properties
|
|
33
33
|
protected _wrappedObject: any = null;
|
|
34
34
|
protected _selected = false;
|
|
35
|
+
protected _locked = false;
|
|
36
|
+
protected _autoFit = false;
|
|
35
37
|
protected _grabbed = false;
|
|
38
|
+
protected _activeAction = '';
|
|
39
|
+
protected _userData = {};
|
|
36
40
|
protected _canvas: AbstractCanvas = null;
|
|
37
41
|
protected _observable: Observable = new Observable(this);
|
|
38
42
|
|
|
@@ -41,6 +45,7 @@ export abstract class AbstractCanvasObject {
|
|
|
41
45
|
|
|
42
46
|
constructor(options?: any) {
|
|
43
47
|
this.initOptions(options);
|
|
48
|
+
this._observable.on(CanvasObjectEvents.OnChange, this.updateConstraints.bind(this));
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
initOptions(options?: any) {
|
|
@@ -75,6 +80,9 @@ export abstract class AbstractCanvasObject {
|
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
set x(x: number) {
|
|
83
|
+
if (x === this._x) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
78
86
|
this._x = x;
|
|
79
87
|
this.setPosition(this._x, this._y);
|
|
80
88
|
this._observable.triggerEvent(CanvasObjectEvents.OnChange);
|
|
@@ -84,7 +92,10 @@ export abstract class AbstractCanvasObject {
|
|
|
84
92
|
return this._x;
|
|
85
93
|
}
|
|
86
94
|
|
|
87
|
-
set y(y: number)
|
|
95
|
+
set y(y: number) {
|
|
96
|
+
if (y === this._y) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
88
99
|
this._y = y;
|
|
89
100
|
this.setPosition(this._x, this._y);
|
|
90
101
|
this._observable.triggerEvent(CanvasObjectEvents.OnChange);
|
|
@@ -95,7 +106,11 @@ export abstract class AbstractCanvasObject {
|
|
|
95
106
|
}
|
|
96
107
|
|
|
97
108
|
set rotation(rotation: number) {
|
|
98
|
-
|
|
109
|
+
const rot = (360 + rotation) % 360;
|
|
110
|
+
if (rot === this._rotation) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this._rotation = rot;
|
|
99
114
|
this.setRotation(this._rotation);
|
|
100
115
|
this._observable.triggerEvent(CanvasObjectEvents.OnChange);
|
|
101
116
|
}
|
|
@@ -105,6 +120,9 @@ export abstract class AbstractCanvasObject {
|
|
|
105
120
|
}
|
|
106
121
|
|
|
107
122
|
set scaling(scaling: number) {
|
|
123
|
+
if (scaling === this._scaling || !Number.isFinite(scaling)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
108
126
|
this._scaling = scaling;
|
|
109
127
|
this.setScalingWithFactor(scaling);
|
|
110
128
|
this._observable.triggerEvent(CanvasObjectEvents.OnChange);
|
|
@@ -116,7 +134,6 @@ export abstract class AbstractCanvasObject {
|
|
|
116
134
|
|
|
117
135
|
set wrappedObject(object: any) {
|
|
118
136
|
this._wrappedObject = object;
|
|
119
|
-
//this.initOptions(this.getOptionsFromWrappedObject());
|
|
120
137
|
this.setOptionsFromObject(this.toObject());
|
|
121
138
|
this.initObjectEvents();
|
|
122
139
|
}
|
|
@@ -140,6 +157,33 @@ export abstract class AbstractCanvasObject {
|
|
|
140
157
|
return this._selected;
|
|
141
158
|
}
|
|
142
159
|
|
|
160
|
+
set locked(locked: boolean) {
|
|
161
|
+
this._locked = locked;
|
|
162
|
+
this._observable.triggerEvent(CanvasObjectEvents.OnChange);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
get locked(): boolean {
|
|
166
|
+
return this._locked;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
set autoFit(autoFit: boolean) {
|
|
170
|
+
this._autoFit = autoFit;
|
|
171
|
+
this._observable.triggerEvent(CanvasObjectEvents.OnChange);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
get autoFit(): boolean {
|
|
175
|
+
return this._autoFit;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
get userData(): Record<string, unknown> {
|
|
179
|
+
return this._userData;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
set userData(userDataObject: Record<string, unknown>) {
|
|
183
|
+
this._userData = userDataObject;
|
|
184
|
+
this._observable.triggerEvent(CanvasObjectEvents.OnChange);
|
|
185
|
+
}
|
|
186
|
+
|
|
143
187
|
set grabbed(grabbed) {
|
|
144
188
|
this._grabbed = grabbed;
|
|
145
189
|
this._observable.triggerEvent(CanvasObjectEvents.OnChange);
|
|
@@ -149,6 +193,15 @@ export abstract class AbstractCanvasObject {
|
|
|
149
193
|
return this._grabbed;
|
|
150
194
|
}
|
|
151
195
|
|
|
196
|
+
set activeAction(action: string) {
|
|
197
|
+
this._activeAction = action;
|
|
198
|
+
this._observable.triggerEvent(CanvasObjectEvents.OnChange);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
get activeAction(): string {
|
|
202
|
+
return this._activeAction;
|
|
203
|
+
}
|
|
204
|
+
|
|
152
205
|
set canvas(canvas: AbstractCanvas) {
|
|
153
206
|
this._canvas = canvas;
|
|
154
207
|
}
|
|
@@ -183,6 +236,8 @@ export abstract class AbstractCanvasObject {
|
|
|
183
236
|
|
|
184
237
|
abstract setSelected(selected: boolean): void;
|
|
185
238
|
|
|
239
|
+
abstract setLocked(locked: boolean): void;
|
|
240
|
+
|
|
186
241
|
abstract initObjectEvents(): void;
|
|
187
242
|
|
|
188
243
|
abstract getTransformedRect(): any;
|
|
@@ -202,13 +257,15 @@ export abstract class AbstractCanvasObject {
|
|
|
202
257
|
}
|
|
203
258
|
|
|
204
259
|
getState() {
|
|
205
|
-
const { selected, grabbed, isFirst, isLast } = this;
|
|
260
|
+
const { selected, grabbed, isFirst, isLast, locked, autoFit } = this;
|
|
206
261
|
return {
|
|
207
262
|
...this.toObject(),
|
|
208
263
|
selected,
|
|
209
264
|
grabbed,
|
|
210
265
|
isFirst,
|
|
211
266
|
isLast,
|
|
267
|
+
locked,
|
|
268
|
+
autoFit,
|
|
212
269
|
};
|
|
213
270
|
}
|
|
214
271
|
|
|
@@ -232,13 +289,16 @@ export abstract class AbstractCanvasObject {
|
|
|
232
289
|
}
|
|
233
290
|
|
|
234
291
|
toObject(includeWrappedObject = false) {
|
|
235
|
-
const { type, x, y, rotation, scaling, uuid } = this;
|
|
292
|
+
const { type, x, y, rotation, scaling, locked, autoFit, userData, uuid } = this;
|
|
236
293
|
const obj = {
|
|
237
294
|
type,
|
|
238
295
|
x,
|
|
239
296
|
y,
|
|
240
297
|
rotation,
|
|
241
298
|
scaling,
|
|
299
|
+
locked,
|
|
300
|
+
autoFit,
|
|
301
|
+
userData,
|
|
242
302
|
uuid,
|
|
243
303
|
};
|
|
244
304
|
if (includeWrappedObject) {
|
|
@@ -306,4 +366,8 @@ export abstract class AbstractCanvasObject {
|
|
|
306
366
|
height: oh * scaling,
|
|
307
367
|
};
|
|
308
368
|
}
|
|
369
|
+
|
|
370
|
+
updateConstraints() {
|
|
371
|
+
this.autoFit && this.fitCanvas(true, true);
|
|
372
|
+
}
|
|
309
373
|
}
|
|
@@ -38,6 +38,7 @@ export class Editor extends React.Component {
|
|
|
38
38
|
canvas: PropTypes.instanceOf(AbstractCanvas).isRequired,
|
|
39
39
|
classes: PropTypes.object.isRequired,
|
|
40
40
|
containerClassName: PropTypes.string,
|
|
41
|
+
renderInCanvasContainer: PropTypes.func,
|
|
41
42
|
};
|
|
42
43
|
|
|
43
44
|
static defaultProps = {
|
|
@@ -163,6 +164,7 @@ export class Editor extends React.Component {
|
|
|
163
164
|
Rulers,
|
|
164
165
|
SelectionToolbox,
|
|
165
166
|
StandardToolbox,
|
|
167
|
+
renderInCanvasContainer,
|
|
166
168
|
} = props;
|
|
167
169
|
if (typeof children === 'function') {
|
|
168
170
|
return children({
|
|
@@ -222,6 +224,7 @@ export class Editor extends React.Component {
|
|
|
222
224
|
Rulers,
|
|
223
225
|
},
|
|
224
226
|
})}
|
|
227
|
+
{renderInCanvasContainer && renderInCanvasContainer()}
|
|
225
228
|
</CanvasContainer>
|
|
226
229
|
</EditorContainer>
|
|
227
230
|
{this.renderSelectionToolbox({
|
|
@@ -75,6 +75,8 @@ class InlineToolBox extends React.Component {
|
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
selectedObject.activeAction = 'scale';
|
|
79
|
+
|
|
78
80
|
const clientPosition = this.getClientPositionFromEvent(evt);
|
|
79
81
|
|
|
80
82
|
let iDistance = selectedObject.getDistanceToCenter(clientPosition.x, clientPosition.y);
|
|
@@ -99,6 +101,7 @@ class InlineToolBox extends React.Component {
|
|
|
99
101
|
this.updateToolbarTransform();
|
|
100
102
|
};
|
|
101
103
|
const mouseUp = evt => {
|
|
104
|
+
selectedObject.activeAction = '';
|
|
102
105
|
const clientPosition = this.getClientPositionFromEvent(evt);
|
|
103
106
|
evt.preventDefault();
|
|
104
107
|
document.removeEventListener(clientPosition.isTouchEvent ? 'touchmove' : 'mousemove', mouseMove, {
|
|
@@ -118,6 +121,8 @@ class InlineToolBox extends React.Component {
|
|
|
118
121
|
return;
|
|
119
122
|
}
|
|
120
123
|
|
|
124
|
+
selectedObject.activeAction = 'rotate';
|
|
125
|
+
|
|
121
126
|
const clientPosition = this.getClientPositionFromEvent(evt);
|
|
122
127
|
|
|
123
128
|
// const { canvasPosition } = this.props;
|
|
@@ -140,6 +145,7 @@ class InlineToolBox extends React.Component {
|
|
|
140
145
|
this.updateToolbarTransform();
|
|
141
146
|
};
|
|
142
147
|
const mouseUp = evt => {
|
|
148
|
+
selectedObject.activeAction = '';
|
|
143
149
|
const clientPosition = this.getClientPositionFromEvent(evt);
|
|
144
150
|
evt.preventDefault();
|
|
145
151
|
|
|
@@ -263,26 +269,34 @@ class InlineToolBox extends React.Component {
|
|
|
263
269
|
},
|
|
264
270
|
});
|
|
265
271
|
}
|
|
272
|
+
if (!selectedObject) {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
266
275
|
switch (positionName) {
|
|
267
276
|
case 'topRight':
|
|
268
277
|
return (
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
278
|
+
!selectedObject.locked && (
|
|
279
|
+
<InlineToolboxButton
|
|
280
|
+
style={{
|
|
281
|
+
background: 'red',
|
|
282
|
+
}}
|
|
283
|
+
onTouchStart={onRotationChange}
|
|
284
|
+
onMouseDown={onRotationChange}
|
|
285
|
+
/>
|
|
286
|
+
)
|
|
276
287
|
);
|
|
277
288
|
case 'bottomRight':
|
|
278
289
|
return (
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
290
|
+
!selectedObject.locked &&
|
|
291
|
+
!selectedObject.autoFit && (
|
|
292
|
+
<InlineToolboxButton
|
|
293
|
+
style={{
|
|
294
|
+
background: 'green',
|
|
295
|
+
}}
|
|
296
|
+
onTouchStart={onScalingChange}
|
|
297
|
+
onMouseDown={onScalingChange}
|
|
298
|
+
/>
|
|
299
|
+
)
|
|
286
300
|
);
|
|
287
301
|
case 'bottomLeft':
|
|
288
302
|
return (
|
|
@@ -72,6 +72,22 @@ export class SelectionToolbox extends React.Component {
|
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
+
onLockChange = evt => {
|
|
76
|
+
const { canvas } = this.props;
|
|
77
|
+
const { selectedObject } = canvas;
|
|
78
|
+
if (selectedObject) {
|
|
79
|
+
selectedObject.locked = evt.target.checked;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
onAutoFitChange = evt => {
|
|
84
|
+
const { canvas } = this.props;
|
|
85
|
+
const { selectedObject } = canvas;
|
|
86
|
+
if (selectedObject) {
|
|
87
|
+
selectedObject.autoFit = evt.target.checked;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
75
91
|
renderObjectTools(renderObj) {
|
|
76
92
|
const { renderObjectTools } = this.props;
|
|
77
93
|
if (renderObjectTools) {
|
|
@@ -85,6 +101,8 @@ export class SelectionToolbox extends React.Component {
|
|
|
85
101
|
onScalingChange,
|
|
86
102
|
onMoveUpClick,
|
|
87
103
|
onMoveDownClick,
|
|
104
|
+
onLockChange,
|
|
105
|
+
onAutoFitChange,
|
|
88
106
|
} = renderObj;
|
|
89
107
|
return (
|
|
90
108
|
<React.Fragment>
|
|
@@ -108,6 +126,28 @@ export class SelectionToolbox extends React.Component {
|
|
|
108
126
|
Down
|
|
109
127
|
</button>
|
|
110
128
|
</ToolboxRow>
|
|
129
|
+
<ToolboxRow>
|
|
130
|
+
<label htmlFor="lock">
|
|
131
|
+
Lock element
|
|
132
|
+
<input
|
|
133
|
+
type="checkbox"
|
|
134
|
+
id="lock"
|
|
135
|
+
name="autoFit"
|
|
136
|
+
checked={selectedObject.locked}
|
|
137
|
+
onChange={onLockChange}
|
|
138
|
+
/>
|
|
139
|
+
</label>
|
|
140
|
+
<label htmlFor="autoFit">
|
|
141
|
+
Auto fit
|
|
142
|
+
<input
|
|
143
|
+
type="checkbox"
|
|
144
|
+
id="autoFit"
|
|
145
|
+
name="autoFit"
|
|
146
|
+
checked={selectedObject.autoFit}
|
|
147
|
+
onChange={onAutoFitChange}
|
|
148
|
+
/>
|
|
149
|
+
</label>
|
|
150
|
+
</ToolboxRow>
|
|
111
151
|
</React.Fragment>
|
|
112
152
|
);
|
|
113
153
|
}
|
|
@@ -127,7 +167,16 @@ export class SelectionToolbox extends React.Component {
|
|
|
127
167
|
|
|
128
168
|
render() {
|
|
129
169
|
logger.log('render SelectionToolbox');
|
|
130
|
-
const {
|
|
170
|
+
const {
|
|
171
|
+
props,
|
|
172
|
+
onRotationChange,
|
|
173
|
+
onScalingChange,
|
|
174
|
+
onMoveUpClick,
|
|
175
|
+
onMoveDownClick,
|
|
176
|
+
onLockChange,
|
|
177
|
+
onAutoFitChange,
|
|
178
|
+
state,
|
|
179
|
+
} = this;
|
|
131
180
|
const { children, selectedObject, canvas, classes } = props;
|
|
132
181
|
if (selectedObject) {
|
|
133
182
|
if (typeof children === 'function') {
|
|
@@ -140,6 +189,8 @@ export class SelectionToolbox extends React.Component {
|
|
|
140
189
|
onScalingChange,
|
|
141
190
|
onMoveUpClick,
|
|
142
191
|
onMoveDownClick,
|
|
192
|
+
onLockChange,
|
|
193
|
+
onAutoFitChange,
|
|
143
194
|
components: {
|
|
144
195
|
ToolboxContainer,
|
|
145
196
|
ToolboxRow,
|
|
@@ -158,6 +209,8 @@ export class SelectionToolbox extends React.Component {
|
|
|
158
209
|
onScalingChange,
|
|
159
210
|
onMoveUpClick,
|
|
160
211
|
onMoveDownClick,
|
|
212
|
+
onLockChange,
|
|
213
|
+
onAutoFitChange,
|
|
161
214
|
components: {
|
|
162
215
|
ToolboxRow,
|
|
163
216
|
},
|