@quinninc/pixi-transformer 0.1.2 → 0.1.6

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.
@@ -19,9 +19,9 @@ export declare class Transformer extends Pixi.Container {
19
19
  private target;
20
20
  private movedThreshold;
21
21
  private updateCallbacks;
22
- private onMoveEndCallback?;
23
22
  private handleOpacity;
24
23
  private controlsSize;
24
+ private handleHitAreaScale;
25
25
  private controlsDimOpacity;
26
26
  private controlsStrokeThickness;
27
27
  private lineColor;
@@ -39,6 +39,7 @@ export declare class Transformer extends Pixi.Container {
39
39
  * @param p.lineColor - border line color
40
40
  * @param p.handleColor - handles' fill color
41
41
  * @param p.controlsSize - handles' size in pixels
42
+ * @param p.handleHitAreaScale - scale factor for handle hit area (e.g. 2 = double size)
42
43
  * @param p.debug - show scaling distance debug lines
43
44
  * @param p.snapKeys - key to hold to enable snapping rotation to 45 degrees // default ['ShiftLeft']
44
45
  * @param p.pivotKeys - key to hold to move the pivot point of transformation // default ['AltLeft']
@@ -61,16 +62,16 @@ export declare class Transformer extends Pixi.Container {
61
62
  *
62
63
  * selectTool.unselect();
63
64
  */
64
- constructor({ id, lineColor, handleColor, controlsSize, debug, generateAnchorMark, snapKeys, pivotKeys, onMoveEnd, }?: {
65
+ constructor({ id, lineColor, handleColor, controlsSize, handleHitAreaScale, debug, generateAnchorMark, snapKeys, pivotKeys, }?: {
65
66
  id?: string;
66
67
  lineColor?: string | number;
67
68
  handleColor?: string | number;
68
69
  controlsSize?: number;
70
+ handleHitAreaScale?: number;
69
71
  debug?: boolean;
70
72
  generateAnchorMark?: false | ((graphic: Pixi.Graphics) => void);
71
73
  snapKeys?: string[];
72
74
  pivotKeys?: string[];
73
- onMoveEnd?: () => void;
74
75
  });
75
76
  private addToolTip;
76
77
  private handleHandleEvents;
@@ -6,6 +6,7 @@ export class Transformer extends Pixi.Container {
6
6
  * @param p.lineColor - border line color
7
7
  * @param p.handleColor - handles' fill color
8
8
  * @param p.controlsSize - handles' size in pixels
9
+ * @param p.handleHitAreaScale - scale factor for handle hit area (e.g. 2 = double size)
9
10
  * @param p.debug - show scaling distance debug lines
10
11
  * @param p.snapKeys - key to hold to enable snapping rotation to 45 degrees // default ['ShiftLeft']
11
12
  * @param p.pivotKeys - key to hold to move the pivot point of transformation // default ['AltLeft']
@@ -28,7 +29,7 @@ export class Transformer extends Pixi.Container {
28
29
  *
29
30
  * selectTool.unselect();
30
31
  */
31
- constructor({ id = "transformer", lineColor = 0x66cfff, handleColor = 0xffffff, controlsSize = 10, debug = false, generateAnchorMark, snapKeys = ["ShiftLeft"], pivotKeys = ["AltLeft"], onMoveEnd, } = {}) {
32
+ constructor({ id = "transformer", lineColor = 0x66cfff, handleColor = 0xffffff, controlsSize = 10, handleHitAreaScale = 2, debug = false, generateAnchorMark, snapKeys = ["ShiftLeft"], pivotKeys = ["AltLeft"], } = {}) {
32
33
  super();
33
34
  // target Pixi.Container
34
35
  this.target = null;
@@ -58,6 +59,7 @@ export class Transformer extends Pixi.Container {
58
59
  this.handleColor = handleColor;
59
60
  this.handleOpacity = 1;
60
61
  this.controlsSize = controlsSize;
62
+ this.handleHitAreaScale = handleHitAreaScale;
61
63
  this.controlsDimOpacity = 1;
62
64
  this.controlsStrokeThickness = 2;
63
65
  this.movedThreshold = 10;
@@ -65,7 +67,6 @@ export class Transformer extends Pixi.Container {
65
67
  this.generateAnchorMark = generateAnchorMark;
66
68
  else if (generateAnchorMark === false)
67
69
  this.generateAnchorMark = () => { };
68
- this.onMoveEndCallback = onMoveEnd;
69
70
  this.zIndex = 1e7;
70
71
  // Pixi.Container Properties
71
72
  this.visible = false;
@@ -92,44 +93,65 @@ export class Transformer extends Pixi.Container {
92
93
  alpha: this.handleOpacity * 0.75,
93
94
  });
94
95
  this.addChild(this.fromPoint, this.toPoint);
96
+ const edgeLong = Math.round(this.controlsSize * 1.6);
97
+ const edgeShort = Math.round(this.controlsSize * 0.7);
98
+ const edgeRadius = Math.max(6, Math.round(edgeShort / 2));
95
99
  // scaling handles
96
100
  this.scaleTHandle = this.createHandle({
97
101
  name: "scaleTHandle",
98
102
  cursor: "n-resize",
103
+ width: edgeLong,
104
+ height: edgeShort,
105
+ radius: edgeRadius,
99
106
  });
100
107
  this.scaleRHandle = this.createHandle({
101
108
  name: "scaleRHandle",
102
109
  cursor: "w-resize",
110
+ width: edgeShort,
111
+ height: edgeLong,
112
+ radius: edgeRadius,
103
113
  });
104
114
  this.scaleBHandle = this.createHandle({
105
115
  name: "scaleBHandle",
106
116
  cursor: "s-resize",
117
+ width: edgeLong,
118
+ height: edgeShort,
119
+ radius: edgeRadius,
107
120
  });
108
121
  this.scaleLHandle = this.createHandle({
109
122
  name: "scaleLHandle",
110
123
  cursor: "e-resize",
124
+ width: edgeShort,
125
+ height: edgeLong,
126
+ radius: edgeRadius,
111
127
  });
112
128
  this.scaleTLHandle = this.createHandle({
113
129
  name: "scaleTLHandle",
114
130
  cursor: "nw-resize",
131
+ shape: "circle",
115
132
  });
116
133
  this.scaleTRHandle = this.createHandle({
117
134
  name: "scaleTRHandle",
118
135
  cursor: "ne-resize",
136
+ shape: "circle",
119
137
  });
120
138
  this.scaleBRHandle = this.createHandle({
121
139
  name: "scaleBRHandle",
122
140
  cursor: "se-resize",
141
+ shape: "circle",
123
142
  });
124
143
  this.scaleBLHandle = this.createHandle({
125
144
  name: "scaleBLHandle",
126
145
  cursor: "sw-resize",
146
+ shape: "circle",
127
147
  });
128
148
  // rotation handle
129
149
  this.rotateHandle = this.createHandle({
130
150
  name: "Rotate",
131
151
  cursor: "pointer",
132
152
  shape: "circle",
153
+ width: Math.round(this.controlsSize * 0.9),
154
+ height: Math.round(this.controlsSize * 0.9),
133
155
  });
134
156
  this.addChild(this.scaleTHandle, this.scaleRHandle, this.scaleBHandle, this.scaleLHandle, this.scaleTLHandle, this.scaleTRHandle, this.scaleBRHandle, this.scaleBLHandle, this.rotateHandle);
135
157
  // ------------<MoveTool>---------------
@@ -144,24 +166,11 @@ export class Transformer extends Pixi.Container {
144
166
  this.moveHandle.hitArea = new Pixi.Rectangle(0, 0, this.controlsSize, this.controlsSize);
145
167
  this.addChild(this.moveHandle);
146
168
  function changeAnchorPoint(ev) {
147
- // console.log("TAPP this, that - ", this, that);
148
169
  if (!that.pivotKey)
149
170
  return;
150
171
  if (!that.target)
151
172
  return;
152
173
  const eventPoint = that.convertToLocal(ev.global);
153
- // console.log("Prev anchor - ", that._anchor);
154
- // console.log("ev.position - ", eventPoint.x, eventPoint.y);
155
- // console.log(
156
- // "that.target.position - ",
157
- // that.target.position.x,
158
- // that.target.position.y,
159
- // );
160
- // console.log(
161
- // "that.target.pivot - ",
162
- // that.target.pivot.x,
163
- // that.target.pivot.y,
164
- // );
165
174
  let dx, dy;
166
175
  // calc new pivot point
167
176
  // step 1 - translate to origin
@@ -177,11 +186,9 @@ export class Transformer extends Pixi.Container {
177
186
  dim: { width: that.target.width, height: that.target.height },
178
187
  anchor: that._anchor,
179
188
  });
180
- // console.log("UP SNAPPING - ", sp, pSnapped);
181
189
  // step 3 - scale by 1/scale
182
190
  rdx = pSnapped.x / that.target.scale.x;
183
191
  rdy = pSnapped.y / that.target.scale.y;
184
- // console.log("3 - dx, dy - ", dx, dy);
185
192
  // step 4 - translate to new pivot
186
193
  const x = that.target.pivot.x + rdx;
187
194
  const y = that.target.pivot.y + rdy;
@@ -195,7 +202,6 @@ export class Transformer extends Pixi.Container {
195
202
  that.target.position.set(posX, posY);
196
203
  }
197
204
  function onMoveHandleDown(downEvent) {
198
- // console.log("onMoveHandleDown this, that - ", this, that);
199
205
  if (!that.target)
200
206
  return;
201
207
  // Store target's starting position for move calculation
@@ -213,7 +219,6 @@ export class Transformer extends Pixi.Container {
213
219
  this.on("globalpointermove", onMoveHandleMove);
214
220
  }
215
221
  function onMoveHandleMove(moveEvent) {
216
- // console.log("onMoveHandleMove this, that - ", this, that);
217
222
  if (!this.dragging || !that.target)
218
223
  return;
219
224
  const eventPoint = that.convertToLocal(moveEvent.global);
@@ -230,7 +235,6 @@ export class Transformer extends Pixi.Container {
230
235
  },
231
236
  anchor: that._anchor,
232
237
  });
233
- // console.log("MOVE SNAPPING - ", p, snappedPoint);
234
238
  that.anchorMark.position.set(snappedPoint.x / that.target.scale.x, snappedPoint.y / that.target.scale.y);
235
239
  return;
236
240
  }
@@ -243,37 +247,25 @@ export class Transformer extends Pixi.Container {
243
247
  moveEvent.stopPropagation();
244
248
  }
245
249
  function onMoveHandleUp(upEvent) {
246
- // console.log("onMoveHandleUp this, that - ", this, that);
247
- const wasDragging = this.dragging; // Capture state before resetting
250
+ const wasDragging = this.dragging;
248
251
  // Reset state for this handle instance first
249
252
  this.off("globalpointermove", onMoveHandleMove);
250
- this.dragging = false; // Reset handle-specific dragging flag
251
- // that.dragging = false; // Reset global dragging flag (might be reset by handleHandleEvents too)
253
+ this.dragging = false;
252
254
  if (this.draggingPivot) {
253
255
  changeAnchorPoint(upEvent);
254
256
  that.anchorMark.position.set(0, 0);
255
257
  this.draggingPivot = false;
256
- // Maybe call update here if pivot change needs immediate visual update?
257
- // that.update();
258
258
  }
259
- // --- Trigger onMoveEnd Callback ---
259
+ // --- Emit Move End Event ---
260
260
  const scale = Math.min(that.scale.x, that.scale.y) || 1;
261
- console.log("this.dragDistance - ", this.dragDistance);
262
- console.log("that.movedThreshold / scale - ", that.movedThreshold / scale);
263
261
  if (wasDragging &&
264
262
  this.dragDistance > that.movedThreshold / scale &&
265
- that.target &&
266
- that.onMoveEndCallback) {
267
- console.log("Move ended, calling onMoveEndCallback (no args)");
268
- that.onMoveEndCallback();
263
+ that.target) {
264
+ that.emit("pixi-transformer-moveend");
269
265
  }
270
- // --- End Trigger ---
266
+ // --- End Emit ---
271
267
  this.dragDistance = 0;
272
- // Note: The generic onHandleUp from handleHandleEvents will also fire
273
- // and call updateCallbacks. Ensure order is okay or adjust if needed.
274
- // If the generic one shouldn't fire its updateCallbacks for this handle,
275
- // you might need to structure handleHandleEvents differently.
276
- upEvent.stopPropagation(); // Prevent event bubbling further if needed
268
+ upEvent.stopPropagation();
277
269
  }
278
270
  // ------------</ MoveTool>---------------
279
271
  // ------------<ScaleXYTool>---------------
@@ -289,14 +281,12 @@ export class Transformer extends Pixi.Container {
289
281
  .on("pointerup", onScaleXYToolUp);
290
282
  }
291
283
  function onScaleXYToolDown(downEvent) {
292
- // console.log("onScaleToolDown this, that - ", this, that);
293
284
  if (!that.target)
294
285
  return;
295
286
  this.targetResolutionStart = that.target.resolution;
296
287
  this.on("globalpointermove", onScaleXYToolMove);
297
288
  }
298
289
  function onScaleXYToolMove(moveEvent) {
299
- // console.log("onScaleToolMove this, that - ", this, that);
300
290
  if (!this.dragging || !that.target)
301
291
  return;
302
292
  const eventPoint = that.convertToLocal(moveEvent.global);
@@ -309,7 +299,6 @@ export class Transformer extends Pixi.Container {
309
299
  that.update();
310
300
  }
311
301
  function onScaleXYToolUp() {
312
- // console.log("onScaleToolUp this, that - ", this, that);
313
302
  if (that.target) {
314
303
  that.target.resolution =
315
304
  this.targetResolutionStart * this.rescaleFactor;
@@ -325,18 +314,15 @@ export class Transformer extends Pixi.Container {
325
314
  .on("pointerupoutside", onScaleYToolUp);
326
315
  }
327
316
  function onScaleYToolDown(downEvent) {
328
- // console.log("onVScaleToolDown this, that - ", this, that);
329
317
  if (!that.target)
330
318
  return;
331
319
  this.on("globalpointermove", onScaleYToolMove);
332
320
  }
333
321
  function onScaleYToolMove(moveEvent) {
334
- // console.log("onVScaleToolMove this - ", this);
335
322
  if (!this.dragging || !that.target)
336
323
  return;
337
324
  const eventPoint = that.convertToLocal(moveEvent.global);
338
325
  const referencePoint = that.target.position.clone();
339
- // referencePoint.x = that.target.position.x + that.target.width / 2;
340
326
  const distStart = calcDistance(this.eventStartPos, referencePoint);
341
327
  const distEnd = calcDistance(eventPoint, referencePoint);
342
328
  const direction = getDirection(referencePoint, this.eventStartPos, eventPoint);
@@ -345,7 +331,6 @@ export class Transformer extends Pixi.Container {
345
331
  that.update();
346
332
  }
347
333
  function onScaleYToolUp(upEvent) {
348
- // console.log("onVScaleToolUp this, that - ", this, that);
349
334
  this.off("globalpointermove", onScaleYToolMove);
350
335
  }
351
336
  // ------------</ ScaleYTool>---------------
@@ -358,18 +343,15 @@ export class Transformer extends Pixi.Container {
358
343
  }
359
344
  this.addChild(this.scaleRHandle);
360
345
  function onScaleXToolDown(downEvent) {
361
- // console.log("onHScaleToolDown this, that - ", this, that);
362
346
  if (!that.target)
363
347
  return;
364
348
  this.on("globalpointermove", onScaleXToolMove);
365
349
  }
366
350
  function onScaleXToolMove(moveEvent) {
367
- // console.log("onHScaleToolMove this - ", this);
368
351
  if (!this.dragging || !that.target)
369
352
  return;
370
353
  const eventPoint = that.convertToLocal(moveEvent.global);
371
354
  const referencePoint = that.target.position.clone();
372
- // referencePoint.y = that.target.position.y + that.target.height / 2;
373
355
  const distStart = calcDistance(this.eventStartPos, referencePoint);
374
356
  const distEnd = calcDistance(eventPoint, referencePoint);
375
357
  const direction = getDirection(referencePoint, this.eventStartPos, eventPoint);
@@ -378,7 +360,6 @@ export class Transformer extends Pixi.Container {
378
360
  that.update();
379
361
  }
380
362
  function onScaleXToolUp(upEvent) {
381
- // console.log("onHScaleToolUp this, that - ", this, that);
382
363
  this.off("globalpointermove", onScaleXToolMove);
383
364
  }
384
365
  // ------------</ ScaleXTool>---------------
@@ -388,13 +369,11 @@ export class Transformer extends Pixi.Container {
388
369
  .on("pointerup", onRotateToolUp)
389
370
  .on("pointerupoutside", onRotateToolUp);
390
371
  function onRotateToolDown(downEvent) {
391
- // console.log("onRotateToolDown this, that - ", this, that);
392
372
  if (!that.target)
393
373
  return;
394
374
  this.on("globalpointermove", onRotateToolMove);
395
375
  }
396
376
  function onRotateToolMove(moveEvent) {
397
- // console.log("onRotateToolMove this, that - ", this, that);
398
377
  if (!this.dragging || !that.target)
399
378
  return;
400
379
  const eventPoint = that.convertToLocal(moveEvent.global);
@@ -425,7 +404,6 @@ export class Transformer extends Pixi.Container {
425
404
  that.update();
426
405
  }
427
406
  function onRotateToolUp(upEvent) {
428
- // console.log("onRotateToolUp this, that - ", this, that);
429
407
  this.off("globalpointermove", onRotateToolMove);
430
408
  }
431
409
  // ------------</ RotateTool>---------------
@@ -449,9 +427,7 @@ export class Transformer extends Pixi.Container {
449
427
  });
450
428
  }
451
429
  handleHandleEvents(handle, that) {
452
- // console.log("handleHandleEvents this, handle - ", this, handle.label);
453
430
  function onHandleDown(e) {
454
- // console.log("onHandleDown this - ", this);
455
431
  that.dragging = true;
456
432
  handle.dragging = true;
457
433
  handle.eventStartPos = that.convertToLocal(e.global.clone());
@@ -464,7 +440,6 @@ export class Transformer extends Pixi.Container {
464
440
  }
465
441
  }
466
442
  function onHandleMove(e) {
467
- // console.log("onHandleMove this - ", this);
468
443
  const eventPoint = that.convertToLocal(e.global.clone());
469
444
  if (that.debug) {
470
445
  that.createHandleIndicatorTo(that.toPoint, eventPoint.x, eventPoint.y);
@@ -472,7 +447,6 @@ export class Transformer extends Pixi.Container {
472
447
  }
473
448
  }
474
449
  function onHandleUp() {
475
- // console.log("onHandleUp this - ", this);
476
450
  that.update();
477
451
  handle.off("globalpointermove", onHandleMove);
478
452
  if (that.debug) {
@@ -504,21 +478,34 @@ export class Transformer extends Pixi.Container {
504
478
  that[property] = false;
505
479
  });
506
480
  }
507
- createHandle({ cursor, name, shape = "square", }) {
481
+ createHandle({ cursor, name, shape = "square", width, height, radius, }) {
482
+ const w = width ?? this.controlsSize;
483
+ const h = height ?? this.controlsSize;
484
+ const r = radius ?? Math.max(4, Math.round(Math.min(w, h) * 0.22));
508
485
  const handle = new Pixi.Graphics();
509
486
  handle.label = this.id;
510
487
  handle.eventMode = "dynamic";
511
488
  handle.alpha = this.handleOpacity;
512
489
  this.addToolTip(handle, name, cursor);
513
490
  if (shape === "circle") {
514
- handle.ellipse(this.controlsSize / 2, this.controlsSize / 2, this.controlsSize / 2, this.controlsSize / 2);
491
+ const radius = Math.min(w, h) / 2;
492
+ handle.ellipse(w / 2, h / 2, radius, radius);
493
+ }
494
+ else {
495
+ handle.roundRect(0, 0, w, h, r);
515
496
  }
516
- else
517
- handle.rect(0, 0, this.controlsSize, this.controlsSize);
518
497
  handle
519
498
  .stroke({ width: this.controlsStrokeThickness, color: this.lineColor })
520
499
  .fill(this.handleColor);
521
- handle.pivot.set(this.controlsSize / 2, this.controlsSize / 2);
500
+ handle.pivot.set(w / 2, h / 2);
501
+ const hitW = w * this.handleHitAreaScale;
502
+ const hitH = h * this.handleHitAreaScale;
503
+ if (shape === "circle") {
504
+ handle.hitArea = new Pixi.Circle(0, 0, Math.max(hitW, hitH) / 2);
505
+ }
506
+ else {
507
+ handle.hitArea = new Pixi.Rectangle(-hitW / 2, -hitH / 2, hitW, hitH);
508
+ }
522
509
  this.handleHandleEvents(handle, this);
523
510
  return handle;
524
511
  }
@@ -552,25 +539,19 @@ export class Transformer extends Pixi.Container {
552
539
  if (this.target) {
553
540
  this.unselect();
554
541
  }
555
- // console.log("select this - ", this);
556
542
  this.target = target;
557
543
  let _anchor;
558
544
  if (this.target.pivot) {
559
- // console.log("target has pivot", this.target.pivot);
560
- // when you set a width of 100 on a sprites with image with actual width of 500, the sprite container is scaled down to 0.2 by default
561
545
  _anchor = new Pixi.Point(this.target.pivot.x / Math.abs(this.target.width / this.target.scale.x), this.target.pivot.y /
562
546
  Math.abs(this.target.height / this.target.scale.y));
563
547
  }
564
548
  else {
565
- // console.log("no-pivot|no-anchor", this.target.pivot);
566
549
  _anchor = new Pixi.Point(0.5, 0.5);
567
550
  }
568
551
  this._anchor = _anchor;
569
552
  if (this.parent !== this.target.parent) {
570
- // console.log("Different parent - switching transformer location position");
571
553
  this.target.parent.addChild(this);
572
554
  }
573
- // console.log("Anchor - ", _anchor);
574
555
  this.update();
575
556
  this.visible = true;
576
557
  }
@@ -586,7 +567,6 @@ export class Transformer extends Pixi.Container {
586
567
  }
587
568
  update() {
588
569
  if (!this.target) {
589
- // console.log("no target, returning...");
590
570
  return;
591
571
  }
592
572
  // copy object translation/transformation
@@ -600,14 +580,12 @@ export class Transformer extends Pixi.Container {
600
580
  this.rotation = this.target.rotation;
601
581
  let _anchor;
602
582
  if (this.target.pivot) {
603
- // console.log("target has pivot", this.target.pivot);
604
583
  _anchor = new Pixi.Point(this.target.pivot.x / Math.abs(this.target.width / this.scale.x), this.target.pivot.y / Math.abs(this.target.height / this.scale.y));
605
584
  }
606
585
  else {
607
586
  _anchor = this._anchor || new Pixi.Point(0.5, 0.5);
608
587
  }
609
588
  this._anchor = _anchor;
610
- // console.log("Anchor - ", _anchor);
611
589
  this.left = -bounds.width * _anchor.x;
612
590
  this.top = -bounds.height * _anchor.y;
613
591
  this.bottom = bounds.height * (1 - _anchor.y);
@@ -615,7 +593,6 @@ export class Transformer extends Pixi.Container {
615
593
  // anchor mark
616
594
  this.generateAnchorMark?.(this.anchorMark);
617
595
  this.deScale(this.anchorMark);
618
- // this.anchorMark!.rotation = -this.rotation;
619
596
  const rotationHandlePos = {
620
597
  x: (this.left + this.right) / 2,
621
598
  y: this.top - 80 / Math.abs(this.scale.y),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quinninc/pixi-transformer",
3
3
  "private": false,
4
- "version": "0.1.2",
4
+ "version": "0.1.6",
5
5
  "repository": {
6
6
  "url": "https://github.com/Quinn-Care-Private-Limited/pixi-transformer"
7
7
  },