Преглед изворни кода

Add handle to scale selection

dev_h
Finn Krein пре 4 година
родитељ
комит
5086d9a81d
4 измењених фајлова са 183 додато и 49 уклоњено
  1. 2
    2
      client-data/js/board.js
  2. 18
    7
      client-data/js/intersect.js
  3. 147
    40
      client-data/tools/hand/hand.js
  4. 16
    0
      client-data/tools/hand/handle.svg

+ 2
- 2
client-data/js/board.js Прегледај датотеку

@@ -363,9 +363,9 @@ function messageForTool(message) {
363 363
 		else Tools.pendingMessages[name].push(message);
364 364
 	}
365 365
 
366
-	if (message.tool !== 'Hand' && message.deltax != null && message.deltay != null) {
366
+	if (message.tool !== 'Hand' && message.transform != null) {
367 367
 		//this message has special info for the mover
368
-		messageForTool({ tool: 'Hand', type: 'update', deltax: message.deltax || 0, deltay: message.deltay || 0, id: message.id });
368
+	    messageForTool({ tool: 'Hand', type: 'update', transform: message.transform, id: message.id});
369 369
 	}
370 370
 }
371 371
 

+ 18
- 7
client-data/js/intersect.js Прегледај датотеку

@@ -28,20 +28,29 @@ if (!SVGGraphicsElement.prototype.transformedBBox || !SVGGraphicsElement.prototy
28 28
     [pointInTransformedBBox,
29 29
      transformedBBoxIntersects] = (function () {
30 30
 
31
-	var applyTransform = function (m,t) {
31
+	var transformRelative = function (m,t) {
32 32
 	    return [
33 33
 		m.a*t[0]+m.c*t[1],
34 34
 		m.b*t[0]+m.d*t[1]
35 35
 	    ]
36 36
 	}
37 37
 
38
+	var transformAbsolute = function (m,t) {
39
+	    return [
40
+		m.a*t[0]+m.c*t[1]+m.e,
41
+		m.b*t[0]+m.d*t[1]+m.f
42
+	    ]
43
+	}
44
+
38 45
 	SVGGraphicsElement.prototype.transformedBBox = function (scale=1) {
39 46
 	    bbox = this.getBBox();
40 47
 	    tmatrix = this.getCTM();
48
+	    tmatrix.e /= scale;
49
+	    tmatrix.f /= scale;
41 50
 	    return {
42
-		r: [bbox.x + tmatrix.e/scale, bbox.y + tmatrix.f/scale],
43
-		a: applyTransform(tmatrix,[bbox.width/scale,0]),
44
-		b: applyTransform(tmatrix,[0,bbox.height/scale])
51
+		r: transformAbsolute(tmatrix,[bbox.x/scale,bbox.y/scale]),
52
+		a: transformRelative(tmatrix,[bbox.width/scale,0]),
53
+		b: transformRelative(tmatrix,[0,bbox.height/scale])
45 54
 	    }
46 55
 	}
47 56
 
@@ -53,10 +62,12 @@ if (!SVGGraphicsElement.prototype.transformedBBox || !SVGGraphicsElement.prototy
53 62
 		height: this.height.baseVal.value
54 63
 	    };
55 64
 	    tmatrix = this.getCTM();
65
+	    tmatrix.e /= scale;
66
+	    tmatrix.f /= scale;
56 67
 	    return {
57
-		r: [bbox.x + tmatrix.e/scale, bbox.y + tmatrix.f/scale],
58
-		a: applyTransform(tmatrix,[bbox.width/scale,0]),
59
-		b: applyTransform(tmatrix,[0,bbox.height/scale])
68
+		r: transformAbsolute(tmatrix,[bbox.x/scale,bbox.y/scale]),
69
+		a: transformRelative(tmatrix,[bbox.width/scale,0]),
70
+		b: transformRelative(tmatrix,[0,bbox.height/scale])
60 71
 	    }
61 72
 	}
62 73
 

+ 147
- 40
client-data/tools/hand/hand.js Прегледај датотеку

@@ -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
 

+ 16
- 0
client-data/tools/hand/handle.svg Прегледај датотеку

@@ -0,0 +1,16 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<svg role="img" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
3
+ <title>Instagram icon</title>
4
+ <g transform="matrix(2.3668 2.3668 -2.3668 2.3668 13.98 -131.11)" fill="#ff002d">
5
+  <g transform="translate(-.5821 .16648)" fill="#f00">
6
+   <rect transform="rotate(-45)" x="-2.9234" y="40.131" width="5.7222" height="5.8388" ry=".34186" fill="#bdaddf" fill-opacity=".99078" stroke="#000" stroke-linejoin="round" stroke-width=".23901"/>
7
+  </g>
8
+ </g>
9
+ <metadata>
10
+  <rdf:RDF>
11
+   <cc:Work rdf:about="">
12
+    <dc:title>Instagram icon</dc:title>
13
+   </cc:Work>
14
+  </rdf:RDF>
15
+ </metadata>
16
+</svg>

Loading…
Откажи
Сачувај