|
@@ -28,13 +28,14 @@
|
28
|
28
|
var selectorStates = {
|
29
|
29
|
pointing: 0,
|
30
|
30
|
selecting: 1,
|
31
|
|
- moving: 2
|
|
31
|
+ transform: 2
|
32
|
32
|
}
|
33
|
33
|
var selected = null;
|
34
|
34
|
var selected_els = [];
|
35
|
35
|
var selectionRect = createSelectorRect();
|
36
|
|
- var selectionRectTranslation;
|
37
|
|
- var translation_elements = [];
|
|
36
|
+ var selectionRectTransform;
|
|
37
|
+ var currentTransform = null;
|
|
38
|
+ var transform_elements = [];
|
38
|
39
|
var selectorState = selectorStates.pointing;
|
39
|
40
|
var last_sent = 0;
|
40
|
41
|
|
|
@@ -57,11 +58,18 @@
|
57
|
58
|
me.style.display = "";
|
58
|
59
|
},
|
59
|
60
|
duplicateSelection);
|
60
|
|
- var selectionButtons = [deleteButton, duplicateButton];
|
|
61
|
+ var scaleHandle = createButton("scaleHandle", "handle", 14, 14,
|
|
62
|
+ function(me, bbox, s) {
|
|
63
|
+ me.width.baseVal.value = me.origWidth / s;
|
|
64
|
+ me.height.baseVal.value = me.origHeight / s;
|
|
65
|
+ me.x.baseVal.value = bbox.r[0] + bbox.a[0] - me.origWidth/(2*s);
|
|
66
|
+ me.y.baseVal.value = bbox.r[1] + bbox.b[1] - me.origHeight/(2*s);
|
|
67
|
+ me.style.display = "";
|
|
68
|
+ },
|
|
69
|
+ startScalingTransform);
|
|
70
|
+ var selectionButtons = [deleteButton, duplicateButton, scaleHandle];
|
61
|
71
|
|
62
|
|
- function getScale() {
|
63
|
|
- return Tools.drawingArea.getCTM().a;
|
64
|
|
- }
|
|
72
|
+ var getScale = Tools.getScale;
|
65
|
73
|
|
66
|
74
|
function getParentMathematics(el) {
|
67
|
75
|
var target;
|
|
@@ -171,18 +179,50 @@
|
171
|
179
|
|
172
|
180
|
function startMovingElements(x, y, evt) {
|
173
|
181
|
evt.preventDefault();
|
174
|
|
- selectorState = selectorStates.moving;
|
|
182
|
+ selectorState = selectorStates.transform;
|
|
183
|
+ currentTransform = moveSelection;
|
175
|
184
|
selected = { x: x, y: y };
|
176
|
185
|
// Some of the selected elements could have been deleted
|
177
|
186
|
selected_els = selected_els.filter(function(el) {
|
178
|
187
|
return Tools.svg.getElementById(el.id) !== null;
|
179
|
188
|
});
|
180
|
|
- translation_elements = selected_els.map(function(el) {
|
181
|
|
- var tmatrix = get_translate_matrix(el);
|
182
|
|
- return { x: tmatrix.e, y: tmatrix.f };
|
|
189
|
+ transform_elements = selected_els.map(function(el) {
|
|
190
|
+ var tmatrix = get_transform_matrix(el);
|
|
191
|
+ return {
|
|
192
|
+ a: tmatrix.a, b: tmatrix.b, c: tmatrix.c,
|
|
193
|
+ d: tmatrix.d, e: tmatrix.e, f: tmatrix.f
|
|
194
|
+ };
|
|
195
|
+ });
|
|
196
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
197
|
+ selectionRectTransform = { x: tmatrix.e, y: tmatrix.f };
|
|
198
|
+ }
|
|
199
|
+
|
|
200
|
+ function startScalingTransform(x, y, evt) {
|
|
201
|
+ evt.preventDefault();
|
|
202
|
+ hideSelectionButtons();
|
|
203
|
+ selectorState = selectorStates.transform;
|
|
204
|
+ var scale = getScale();
|
|
205
|
+ var bbox = selectionRect.transformedBBox(scale);
|
|
206
|
+ selected = {
|
|
207
|
+ x: bbox.r[0],
|
|
208
|
+ y: bbox.r[1],
|
|
209
|
+ w: bbox.a[0],
|
|
210
|
+ h: bbox.b[1],
|
|
211
|
+ s: scale
|
|
212
|
+ };
|
|
213
|
+ transform_elements = selected_els.map(function(el) {
|
|
214
|
+ var tmatrix = get_transform_matrix(el);
|
|
215
|
+ return {
|
|
216
|
+ a: tmatrix.a, b: tmatrix.b, c: tmatrix.c,
|
|
217
|
+ d: tmatrix.d, e: tmatrix.e, f: tmatrix.f
|
|
218
|
+ };
|
183
|
219
|
});
|
184
|
|
- var tmatrix = get_translate_matrix(selectionRect);
|
185
|
|
- selectionRectTranslation = { x: tmatrix.e, y: tmatrix.f };
|
|
220
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
221
|
+ selectionRectTransform = {
|
|
222
|
+ a: tmatrix.a, d: tmatrix.d,
|
|
223
|
+ e: tmatrix.e, f: tmatrix.f
|
|
224
|
+ };
|
|
225
|
+ currentTransform = scaleSelection;
|
186
|
226
|
}
|
187
|
227
|
|
188
|
228
|
function startSelector(x, y, evt) {
|
|
@@ -195,7 +235,7 @@
|
195
|
235
|
selectionRect.width.baseVal.value = 0;
|
196
|
236
|
selectionRect.height.baseVal.value = 0;
|
197
|
237
|
selectionRect.style.display = "";
|
198
|
|
- tmatrix = get_translate_matrix(selectionRect);
|
|
238
|
+ tmatrix = get_transform_matrix(selectionRect);
|
199
|
239
|
tmatrix.e = 0;
|
200
|
240
|
tmatrix.f = 0;
|
201
|
241
|
}
|
|
@@ -217,19 +257,73 @@
|
217
|
257
|
var dx = x - selected.x;
|
218
|
258
|
var dy = y - selected.y;
|
219
|
259
|
var msgs = selected_els.map(function(el, i) {
|
220
|
|
- return {
|
221
|
|
- type: "update",
|
222
|
|
- id: el.id,
|
223
|
|
- deltax: dx + translation_elements[i].x,
|
224
|
|
- deltay: dy + translation_elements[i].y
|
225
|
|
- };
|
226
|
|
- })
|
|
260
|
+ var oldTransform = transform_elements[i];
|
|
261
|
+ return {
|
|
262
|
+ type: "update",
|
|
263
|
+ id: el.id,
|
|
264
|
+ transform: {
|
|
265
|
+ a: oldTransform.a,
|
|
266
|
+ b: oldTransform.b,
|
|
267
|
+ c: oldTransform.c,
|
|
268
|
+ d: oldTransform.d,
|
|
269
|
+ e: dx + oldTransform.e,
|
|
270
|
+ f: dy + oldTransform.f
|
|
271
|
+ }
|
|
272
|
+ };
|
|
273
|
+ })
|
|
274
|
+ var msg = {
|
|
275
|
+ _children: msgs
|
|
276
|
+ };
|
|
277
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
278
|
+ tmatrix.e = dx + selectionRectTransform.x;
|
|
279
|
+ tmatrix.f = dy + selectionRectTransform.y;
|
|
280
|
+ var now = performance.now();
|
|
281
|
+ if (now - last_sent > 70) {
|
|
282
|
+ last_sent = now;
|
|
283
|
+ Tools.drawAndSend(msg);
|
|
284
|
+ } else {
|
|
285
|
+ draw(msg);
|
|
286
|
+ }
|
|
287
|
+ }
|
|
288
|
+
|
|
289
|
+ function scaleSelection(x, y) {
|
|
290
|
+ var rx = (x - selected.x)/(selected.w);
|
|
291
|
+ var ry = (y - selected.y)/(selected.h);
|
|
292
|
+ var scale = getScale();
|
|
293
|
+ var msgs = selected_els.map(function(el, i) {
|
|
294
|
+ var oldTransform = transform_elements[i];
|
|
295
|
+ var x = el.transformedBBox(scale).r[0];
|
|
296
|
+ var y = el.transformedBBox(scale).r[1];
|
|
297
|
+ var a = oldTransform.a * rx;
|
|
298
|
+ var d = oldTransform.d * ry;
|
|
299
|
+ var e = selected.x * (1 - rx) - x * a +
|
|
300
|
+ (x * oldTransform.a + oldTransform.e) * rx
|
|
301
|
+ var f = selected.y * (1 - ry) - y * d +
|
|
302
|
+ (y * oldTransform.d + oldTransform.f) * ry
|
|
303
|
+ return {
|
|
304
|
+ type: "update",
|
|
305
|
+ id: el.id,
|
|
306
|
+ transform: {
|
|
307
|
+ a: a,
|
|
308
|
+ b: oldTransform.b,
|
|
309
|
+ c: oldTransform.c,
|
|
310
|
+ d: d,
|
|
311
|
+ e: e,
|
|
312
|
+ f: f
|
|
313
|
+ }
|
|
314
|
+ };
|
|
315
|
+ })
|
227
|
316
|
var msg = {
|
228
|
317
|
_children: msgs
|
229
|
318
|
};
|
230
|
|
- var tmatrix = get_translate_matrix(selectionRect);
|
231
|
|
- tmatrix.e = dx + selectionRectTranslation.x;
|
232
|
|
- tmatrix.f = dy + selectionRectTranslation.y;
|
|
319
|
+
|
|
320
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
321
|
+ tmatrix.a = rx;
|
|
322
|
+ tmatrix.d = ry;
|
|
323
|
+ tmatrix.e = selectionRectTransform.e +
|
|
324
|
+ selectionRect.x.baseVal.value * (selectionRectTransform.a - rx)
|
|
325
|
+ tmatrix.f = selectionRectTransform.f +
|
|
326
|
+ selectionRect.y.baseVal.value * (selectionRectTransform.d - ry)
|
233
|
327
|
var now = performance.now();
|
234
|
328
|
if (now - last_sent > 70) {
|
235
|
329
|
last_sent = now;
|
|
@@ -246,23 +340,34 @@
|
246
|
340
|
rect.height.baseVal.value = Math.abs(y - selected.y);
|
247
|
341
|
}
|
248
|
342
|
|
249
|
|
- function get_translate_matrix(elem) {
|
|
343
|
+ function resetSelectionRect() {
|
|
344
|
+ var bbox = selectionRect.transformedBBox(getScale());
|
|
345
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
346
|
+ selectionRect.x.baseVal.value = bbox.r[0];
|
|
347
|
+ selectionRect.y.baseVal.value = bbox.r[1];
|
|
348
|
+ selectionRect.width.baseVal.value = bbox.a[0];
|
|
349
|
+ selectionRect.height.baseVal.value = bbox.b[1];
|
|
350
|
+ tmatrix.a = 1; tmatrix.b = 0; tmatrix.c = 0;
|
|
351
|
+ tmatrix.d = 1; tmatrix.e = 0; tmatrix.f = 0;
|
|
352
|
+ }
|
|
353
|
+
|
|
354
|
+ function get_transform_matrix(elem) {
|
250
|
355
|
// Returns the first translate or transform matrix or makes one
|
251
|
|
- var translate = null;
|
|
356
|
+ var transform = null;
|
252
|
357
|
for (var i = 0; i < elem.transform.baseVal.numberOfItems; ++i) {
|
253
|
358
|
var baseVal = elem.transform.baseVal[i];
|
254
|
359
|
// quick tests showed that even if one changes only the fields e and f or uses createSVGTransformFromMatrix
|
255
|
360
|
// the brower may add a SVG_TRANSFORM_MATRIX instead of a SVG_TRANSFORM_TRANSLATE
|
256
|
|
- if (baseVal.type === SVGTransform.SVG_TRANSFORM_TRANSLATE || baseVal.type === SVGTransform.SVG_TRANSFORM_MATRIX) {
|
257
|
|
- translate = baseVal;
|
|
361
|
+ if (baseVal.type === SVGTransform.SVG_TRANSFORM_MATRIX) {
|
|
362
|
+ transform = baseVal;
|
258
|
363
|
break;
|
259
|
364
|
}
|
260
|
365
|
}
|
261
|
|
- if (translate == null) {
|
262
|
|
- translate = elem.transform.baseVal.createSVGTransformFromMatrix(Tools.svg.createSVGMatrix());
|
263
|
|
- elem.transform.baseVal.appendItem(translate);
|
|
366
|
+ if (transform == null) {
|
|
367
|
+ transform = elem.transform.baseVal.createSVGTransformFromMatrix(Tools.svg.createSVGMatrix());
|
|
368
|
+ elem.transform.baseVal.appendItem(transform);
|
264
|
369
|
}
|
265
|
|
- return translate.matrix;
|
|
370
|
+ return transform.matrix;
|
266
|
371
|
}
|
267
|
372
|
|
268
|
373
|
function draw(data) {
|
|
@@ -274,9 +379,10 @@
|
274
|
379
|
case "update":
|
275
|
380
|
var elem = Tools.svg.getElementById(data.id);
|
276
|
381
|
if (!elem) throw new Error("Mover: Tried to move an element that does not exist.");
|
277
|
|
- var tmatrix = get_translate_matrix(elem);
|
278
|
|
- tmatrix.e = data.deltax || 0;
|
279
|
|
- tmatrix.f = data.deltay || 0;
|
|
382
|
+ var tmatrix = get_transform_matrix(elem);
|
|
383
|
+ for (i in data.transform) {
|
|
384
|
+ tmatrix[i] = data.transform[i]
|
|
385
|
+ }
|
280
|
386
|
break;
|
281
|
387
|
case "copy":
|
282
|
388
|
var newElement = Tools.svg.getElementById(data.id).cloneNode(true);
|
|
@@ -303,7 +409,7 @@
|
303
|
409
|
}
|
304
|
410
|
}
|
305
|
411
|
if (button) {
|
306
|
|
- button.clickCallback();
|
|
412
|
+ button.clickCallback(x, y, evt);
|
307
|
413
|
} else if (pointInTransformedBBox([x, y], selectionRect.transformedBBox(scale))) {
|
308
|
414
|
hideSelectionButtons();
|
309
|
415
|
startMovingElements(x, y, evt);
|
|
@@ -323,17 +429,18 @@
|
323
|
429
|
if (selected_els.length == 0) {
|
324
|
430
|
hideSelectionUI();
|
325
|
431
|
}
|
326
|
|
- }
|
|
432
|
+ } else if (selectorState == selectorStates.transform)
|
|
433
|
+ resetSelectionRect();
|
327
|
434
|
if (selected_els.length != 0) showSelectionButtons();
|
328
|
|
- translation_elements = [];
|
|
435
|
+ transform_elements = [];
|
329
|
436
|
selectorState = selectorStates.pointing;
|
330
|
437
|
}
|
331
|
438
|
|
332
|
439
|
function moveSelector(x, y, evt) {
|
333
|
440
|
if (selectorState == selectorStates.selecting) {
|
334
|
441
|
updateRect(x, y, selectionRect);
|
335
|
|
- } else if (selectorState == selectorStates.moving) {
|
336
|
|
- moveSelection(x, y, selectionRect);
|
|
442
|
+ } else if (selectorState == selectorStates.transform && currentTransform) {
|
|
443
|
+ currentTransform(x, y);
|
337
|
444
|
}
|
338
|
445
|
}
|
339
|
446
|
|