@quinninc/pixi-transformer 0.0.1 → 0.0.3

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/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  Works with pixi.js v8 and above.
4
4
 
5
- ![preview](example/public/image.png)
5
+ ![preview](https://cdn.quinn.live/transformer-image.png)
6
6
 
7
7
  ### ✨ Features
8
8
 
9
9
  - Translate - Drag to move anywhere
10
10
  - Scale - Scale on X, Y or both axis'
11
11
  - Rotate - drag to rotate
12
- - Anchor point - update anchor point of transforms
12
+ - Anchor point - update anchor point of transforms (Ctrl + Click)
13
13
  - Snapping - hold ctrl to snap rotation at 45degrees, snap anchor point to edges and corners.
14
14
  - Theming - custom border color, control size and color, and anchor point graphic
15
15
 
@@ -48,8 +48,6 @@ obj.on("pointertap", (ev) => {
48
48
 
49
49
  ## API
50
50
 
51
- <!-- INSERT GENERATED DOCS START -->
52
-
53
51
  ### `FreeTransformTool` (class)
54
52
 
55
53
  **Constructor Parameter Object:**
@@ -61,5 +59,3 @@ obj.on("pointertap", (ev) => {
61
59
  - `generateAnchorMark` - a function to generate your custom anchor mark. default - `undefined` (uses default anchor mark)
62
60
 
63
61
  **returns:** `PIXI.Container` (the select tool)
64
-
65
- <!-- INSERT GENERATED DOCS END -->
@@ -1,6 +1,7 @@
1
- import { Container, Graphics, Sprite } from "pixi.js";
2
- export declare class FreeTransformTool extends Container {
1
+ import { Pixi } from "./pixi";
2
+ export declare class Transformer extends Pixi.Container {
3
3
  private debug;
4
+ private id;
4
5
  private moveHandle;
5
6
  private rotateHandle;
6
7
  private scaleTHandle;
@@ -27,6 +28,7 @@ export declare class FreeTransformTool extends Container {
27
28
  private top;
28
29
  private bottom;
29
30
  private right;
31
+ private _anchor;
30
32
  private dragging;
31
33
  /**
32
34
  *
@@ -51,24 +53,26 @@ export declare class FreeTransformTool extends Container {
51
53
  *
52
54
  * selectTool.unselect();
53
55
  */
54
- constructor({ lineColor, handleColor, controlsSize, debug, generateAnchorMark, }?: {
56
+ constructor({ id, lineColor, handleColor, controlsSize, debug, generateAnchorMark, }?: {
57
+ id?: string;
55
58
  lineColor?: string | number;
56
59
  handleColor?: string | number;
57
60
  controlsSize?: number;
58
61
  debug?: boolean;
59
- generateAnchorMark?: false | ((graphic: Graphics) => void);
62
+ generateAnchorMark?: false | ((graphic: Pixi.Graphics) => void);
60
63
  });
61
64
  private addToolTip;
62
65
  private handleHandleEvents;
63
66
  private createHandle;
64
67
  private createHandleIndicatorTo;
65
68
  private deScale;
66
- select(target: Container): void;
69
+ select(target: Pixi.Container): void;
70
+ onUpdate: () => void;
67
71
  unselect(): void;
68
72
  update(): void;
69
73
  setTitle(title: string): void;
70
74
  setCursor(cursor: string): void;
71
75
  private generateAnchorMark;
72
- get _target(): Container<import("pixi.js").ContainerChild> | Sprite | null;
76
+ get _target(): Pixi.Container<Pixi.ContainerChild> | Pixi.Sprite | null;
73
77
  cleanup(): void;
74
78
  }
@@ -1,6 +1,6 @@
1
- import { Container, Graphics, Point, Rectangle, } from "pixi.js";
2
- import { calcAngleRadians, calcDistance, getDirection, rotatePoint, } from "./vector";
3
- export class FreeTransformTool extends Container {
1
+ import { Pixi } from "./pixi";
2
+ import { calcAngleRadians, calcDistance, getDirection, rotatePoint, snapToEdgesAndCorners, } from "./vector";
3
+ export class Transformer extends Pixi.Container {
4
4
  /**
5
5
  *
6
6
  * @param p.lineColor - border line color
@@ -24,17 +24,20 @@ export class FreeTransformTool extends Container {
24
24
  *
25
25
  * selectTool.unselect();
26
26
  */
27
- constructor({ lineColor = 0x66cfff, handleColor = 0xffffff, controlsSize = 10, debug = false, generateAnchorMark, } = {}) {
27
+ constructor({ id = "transformer", lineColor = 0x66cfff, handleColor = 0xffffff, controlsSize = 10, debug = false, generateAnchorMark, } = {}) {
28
28
  super();
29
- // target container
29
+ // target Pixi.Container
30
30
  this.target = null;
31
31
  // position state
32
32
  this.left = 0;
33
33
  this.top = 0;
34
34
  this.bottom = 0;
35
35
  this.right = 0;
36
+ this._anchor = new Pixi.Point(0, 0);
36
37
  this.dragging = false;
38
+ this.onUpdate = () => { };
37
39
  const that = this;
40
+ this.id = id;
38
41
  this.debug = debug;
39
42
  this.lineColor = lineColor;
40
43
  this.handleColor = handleColor;
@@ -48,21 +51,24 @@ export class FreeTransformTool extends Container {
48
51
  else if (generateAnchorMark === false)
49
52
  this.generateAnchorMark = () => { };
50
53
  this.zIndex = 1e7;
51
- // Container Properties
54
+ // Pixi.Container Properties
52
55
  this.visible = false;
53
56
  // create border
54
- this.border = new Graphics({ label: "Border" });
57
+ this.border = new Pixi.Graphics({ label: "Border" });
55
58
  this.addChild(this.border);
56
59
  // Anchor mark
57
- this.anchorMark = new Graphics({ label: "AnchorMark" });
60
+ this.anchorMark = new Pixi.Graphics({
61
+ label: "AnchorMark",
62
+ eventMode: "none",
63
+ });
58
64
  this.anchorMark.alpha = this.handleOpacity;
59
65
  this.addChild(this.anchorMark);
60
66
  // debug indicators
61
- this.fromPoint = new Graphics({
67
+ this.fromPoint = new Pixi.Graphics({
62
68
  label: "fromPoint",
63
69
  alpha: this.handleOpacity * 0.75,
64
70
  });
65
- this.toPoint = new Graphics({
71
+ this.toPoint = new Pixi.Graphics({
66
72
  label: "toPoint",
67
73
  alpha: this.handleOpacity * 0.75,
68
74
  });
@@ -108,20 +114,65 @@ export class FreeTransformTool extends Container {
108
114
  });
109
115
  this.addChild(this.scaleTHandle, this.scaleRHandle, this.scaleBHandle, this.scaleLHandle, this.scaleTLHandle, this.scaleTRHandle, this.scaleBRHandle, this.scaleBLHandle, this.rotateHandle);
110
116
  // ------------<MoveTool>---------------
111
- this.moveHandle = new Graphics({ label: "moveHandle" });
112
- this.moveHandle.interactive = true;
117
+ this.moveHandle = new Pixi.Graphics({ label: this.id });
118
+ this.moveHandle.eventMode = "dynamic";
113
119
  this.addToolTip(this.moveHandle, "Move", "move");
114
120
  this.moveHandle
115
121
  .on("pointerdown", onMoveHandleDown)
116
122
  .on("pointerup", onMoveHandleUp)
117
123
  .on("pointerupoutside", onMoveHandleUp);
118
124
  this.handleHandleEvents(this.moveHandle, this);
119
- this.moveHandle.hitArea = new Rectangle(0, 0, this.controlsSize, this.controlsSize);
125
+ this.moveHandle.hitArea = new Pixi.Rectangle(0, 0, this.controlsSize, this.controlsSize);
120
126
  this.addChild(this.moveHandle);
127
+ function changeAnchorPoint(ev) {
128
+ // console.log("TAPP this, that - ", this, that);
129
+ if (!ev.ctrlKey)
130
+ return;
131
+ if (!that.target)
132
+ return;
133
+ console.log("Prev anchor - ", that._anchor);
134
+ console.log("ev.position - ", ev.global.x, ev.global.y);
135
+ console.log("that.target.position - ", that.target.position.x, that.target.position.y);
136
+ console.log("that.target.pivot - ", that.target.pivot.x, that.target.pivot.y);
137
+ let dx, dy;
138
+ // calc new pivot point
139
+ // step 1 - translate to origin
140
+ dx = ev.global.x - that.target.position.x;
141
+ dy = ev.global.y - that.target.position.y;
142
+ // step 2 - rotate by -angle
143
+ const rp = rotatePoint({ x: dx, y: dy }, { x: 0, y: 0 }, -that.target.rotation);
144
+ let rdx = rp.x;
145
+ let rdy = rp.y;
146
+ const sp = { x: rdx, y: rdy };
147
+ const pSnapped = snapToEdgesAndCorners({
148
+ point: sp,
149
+ dim: { width: that.target.width, height: that.target.height },
150
+ anchor: that._anchor,
151
+ });
152
+ // console.log("UP SNAPPING - ", sp, pSnapped);
153
+ // step 3 - scale by 1/scale
154
+ rdx = pSnapped.x / that.target.scale.x;
155
+ rdy = pSnapped.y / that.target.scale.y;
156
+ // console.log("3 - dx, dy - ", dx, dy);
157
+ // step 4 - translate to new pivot
158
+ const x = that.target.pivot.x + rdx;
159
+ const y = that.target.pivot.y + rdy;
160
+ // calc new position
161
+ const rrp = rotatePoint({ x: rdx, y: rdy }, { x: 0, y: 0 }, that.target.rotation);
162
+ rrp.x = rrp.x * that.target.scale.x + that.target.position.x;
163
+ rrp.y = rrp.y * that.target.scale.y + that.target.position.y;
164
+ const posX = rrp.x;
165
+ const posY = rrp.y;
166
+ that.target.pivot.set(x, y);
167
+ that.target.position.set(posX, posY);
168
+ }
121
169
  function onMoveHandleDown(downEvent) {
122
170
  // console.log("onMoveHandleDown this, that - ", this, that);
123
171
  if (!that.target)
124
172
  return;
173
+ if (downEvent.ctrlKey) {
174
+ this.draggingPivot = true;
175
+ }
125
176
  // data
126
177
  this.targetStartPos = that.target.position.clone();
127
178
  this.dragDistance = 0;
@@ -131,7 +182,24 @@ export class FreeTransformTool extends Container {
131
182
  // console.log("onMoveHandleMove this, that - ", this, that);
132
183
  if (!this.dragging || !that.target)
133
184
  return;
134
- const moveDelta = new Point(moveEvent.global.x - this.eventStartGlobalPos.x, moveEvent.global.y - this.eventStartGlobalPos.y);
185
+ if (this.draggingPivot) {
186
+ // changing pivot point
187
+ let x = moveEvent.global.x - that.target.x;
188
+ let y = moveEvent.global.y - that.target.y;
189
+ const p = rotatePoint({ x, y }, { x: 0, y: 0 }, -that.target.rotation);
190
+ const snappedPoint = snapToEdgesAndCorners({
191
+ point: p,
192
+ dim: {
193
+ width: that.target.width,
194
+ height: that.target.height,
195
+ },
196
+ anchor: that._anchor,
197
+ });
198
+ // console.log("MOVE SNAPPING - ", p, snappedPoint);
199
+ that.anchorMark.position.set(snappedPoint.x / that.target.scale.x, snappedPoint.y / that.target.scale.y);
200
+ return;
201
+ }
202
+ const moveDelta = new Pixi.Point(moveEvent.global.x - this.eventStartGlobalPos.x, moveEvent.global.y - this.eventStartGlobalPos.y);
135
203
  that.target.position.x = this.targetStartPos.x + moveDelta.x;
136
204
  that.target.position.y = this.targetStartPos.y + moveDelta.y;
137
205
  this.dragDistance = calcDistance(moveEvent.global, this.eventStartGlobalPos);
@@ -141,12 +209,11 @@ export class FreeTransformTool extends Container {
141
209
  function onMoveHandleUp(upEvent) {
142
210
  // console.log("onMoveHandleUp this, that - ", this, that);
143
211
  upEvent.stopPropagation();
144
- // only deselect if there was very little movement on click
145
- // which helps on mobile devices, where it's difficult to
146
- // tap without dragging slightly
147
- if (!this.dragDistance || this.dragDistance < that.movedThreshold) {
148
- that.unselect();
212
+ if (this.draggingPivot) {
213
+ changeAnchorPoint(upEvent);
214
+ that.anchorMark.position.set(0, 0);
149
215
  }
216
+ this.draggingPivot = false;
150
217
  this.off("globalpointermove", onMoveHandleMove);
151
218
  }
152
219
  // ------------</ MoveTool>---------------
@@ -175,7 +242,7 @@ export class FreeTransformTool extends Container {
175
242
  return;
176
243
  const distStart = calcDistance(this.eventStartGlobalPos, that.target.position);
177
244
  const distEnd = calcDistance(moveEvent.global, that.target.position);
178
- const direction = getDirection(new Point(that.position.x, that.position.y), new Point(this.eventStartGlobalPos.x, this.eventStartGlobalPos.y), new Point(moveEvent.global.x, moveEvent.global.y));
245
+ const direction = getDirection(new Pixi.Point(that.position.x, that.position.y), new Pixi.Point(this.eventStartGlobalPos.x, this.eventStartGlobalPos.y), new Pixi.Point(moveEvent.global.x, moveEvent.global.y));
179
246
  this.rescaleFactor = (distEnd / distStart) * direction;
180
247
  that.target.scale.x = this.targetStartScale.x * this.rescaleFactor;
181
248
  that.target.scale.y = this.targetStartScale.y * this.rescaleFactor;
@@ -357,9 +424,9 @@ export class FreeTransformTool extends Container {
357
424
  .on("pointerupoutside", onHandleUp);
358
425
  }
359
426
  createHandle({ cursor, name, shape = "square", }) {
360
- const handle = new Graphics();
361
- handle.label = name;
362
- handle.interactive = true;
427
+ const handle = new Pixi.Graphics();
428
+ handle.label = this.id;
429
+ handle.eventMode = "dynamic";
363
430
  handle.alpha = this.handleOpacity;
364
431
  this.addToolTip(handle, name, cursor);
365
432
  if (shape === "circle") {
@@ -377,8 +444,8 @@ export class FreeTransformTool extends Container {
377
444
  createHandleIndicatorTo(handle, x, y) {
378
445
  x = x - this.position.x;
379
446
  y = y - this.position.y;
380
- const p1 = new Point(x, y);
381
- const origin = new Point(0, 0);
447
+ const p1 = new Pixi.Point(x, y);
448
+ const origin = new Pixi.Point(0, 0);
382
449
  const p = rotatePoint(p1, origin, -this.rotation);
383
450
  x = p.x;
384
451
  y = p.y;
@@ -401,35 +468,62 @@ export class FreeTransformTool extends Container {
401
468
  this.unselect();
402
469
  return;
403
470
  }
404
- // copy object translation/transformation
471
+ // console.log("select this - ", this);
405
472
  this.target = target;
406
- const bounds = target.getLocalBounds();
473
+ let _anchor;
474
+ if (this.target.pivot) {
475
+ // console.log("target has pivot", this.target.pivot);
476
+ // 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
477
+ _anchor = new Pixi.Point(this.target.pivot.x / Math.abs(this.target.width / this.target.scale.x), this.target.pivot.y /
478
+ Math.abs(this.target.height / this.target.scale.y));
479
+ }
480
+ else {
481
+ // console.log("no-pivot|no-anchor", this.target.pivot);
482
+ _anchor = new Pixi.Point(0.5, 0.5);
483
+ }
484
+ this._anchor = _anchor;
485
+ console.log("Anchor - ", _anchor);
486
+ this.update();
487
+ this.visible = true;
488
+ }
489
+ unselect() {
490
+ this.target = null;
491
+ this.visible = false;
492
+ this.onUpdate();
493
+ }
494
+ update() {
495
+ if (!this.target) {
496
+ console.log("no target, returning...");
497
+ return;
498
+ }
499
+ this.onUpdate();
500
+ // copy object translation/transformation
501
+ const bounds = this.target.getLocalBounds();
407
502
  this.width = bounds.width;
408
503
  this.height = bounds.height;
409
- this.scale.x = target.scale.x;
410
- this.scale.y = target.scale.y;
411
- this.x = target.x;
412
- this.y = target.y;
413
- this.rotation = target.rotation;
414
- let anchor;
415
- if (target.anchor) {
416
- anchor = target.anchor;
417
- }
418
- else if (target.pivot) {
419
- anchor = new Point(target.pivot.x / target.width, target.pivot.y / target.height);
504
+ this.scale.x = this.target.scale.x;
505
+ this.scale.y = this.target.scale.y;
506
+ this.x = this.target.x;
507
+ this.y = this.target.y;
508
+ this.rotation = this.target.rotation;
509
+ let _anchor;
510
+ if (this.target.pivot) {
511
+ // console.log("target has pivot", this.target.pivot);
512
+ _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));
420
513
  }
421
514
  else {
422
- anchor = new Point(0.5, 0.5);
515
+ _anchor = this._anchor || new Pixi.Point(0.5, 0.5);
423
516
  }
424
- target.anchor = anchor;
425
- this.left = -bounds.width * anchor.x;
426
- this.top = -bounds.height * anchor.y;
427
- this.bottom = bounds.height * (1 - anchor.y);
428
- this.right = bounds.width * (1 - anchor.x);
517
+ this._anchor = _anchor;
518
+ // console.log("Anchor - ", _anchor);
519
+ this.left = -bounds.width * _anchor.x;
520
+ this.top = -bounds.height * _anchor.y;
521
+ this.bottom = bounds.height * (1 - _anchor.y);
522
+ this.right = bounds.width * (1 - _anchor.x);
429
523
  // anchor mark
430
524
  this.generateAnchorMark?.(this.anchorMark);
431
525
  this.deScale(this.anchorMark);
432
- this.anchorMark.rotation = -this.rotation;
526
+ // this.anchorMark!.rotation = -this.rotation;
433
527
  const rotationHandlePos = {
434
528
  x: (this.left + this.right) / 2,
435
529
  y: this.top - 80 / Math.abs(this.scale.y),
@@ -460,7 +554,21 @@ export class FreeTransformTool extends Container {
460
554
  color: this.lineColor,
461
555
  });
462
556
  // draw move hit area
463
- this.moveHandle.hitArea = new Rectangle(this.left, this.top, bounds.width, bounds.height);
557
+ let anchorRectPoints = [];
558
+ const isAnchorOutside = this._anchor.x < 0 ||
559
+ this._anchor.y < 0 ||
560
+ this._anchor.x > 1 ||
561
+ this._anchor.y > 1;
562
+ if (isAnchorOutside) {
563
+ anchorRectPoints = [
564
+ new Pixi.Point(-this.controlsSize, -this.controlsSize),
565
+ new Pixi.Point(-this.controlsSize, this.controlsSize),
566
+ new Pixi.Point(this.controlsSize, this.controlsSize),
567
+ new Pixi.Point(this.controlsSize, -this.controlsSize),
568
+ new Pixi.Point(-this.controlsSize, -this.controlsSize),
569
+ ];
570
+ }
571
+ this.moveHandle.hitArea = new Pixi.Polygon(new Pixi.Point(this.left, this.top), new Pixi.Point(this.right, this.top), new Pixi.Point(this.right, this.bottom), new Pixi.Point(this.left, this.bottom), new Pixi.Point(this.left, this.top), ...anchorRectPoints);
464
572
  this.scaleTLHandle.position.set(this.left, this.top);
465
573
  this.scaleTRHandle.position.set(this.right, this.top);
466
574
  this.scaleBRHandle.position.set(this.right, this.bottom);
@@ -485,17 +593,6 @@ export class FreeTransformTool extends Container {
485
593
  allHandles.forEach((handle) => {
486
594
  this.deScale(handle);
487
595
  });
488
- this.visible = true;
489
- // console.log("select this - ", this);
490
- }
491
- unselect() {
492
- this.target = null;
493
- this.visible = false;
494
- }
495
- update() {
496
- if (this.target) {
497
- this.select(this.target);
498
- }
499
596
  }
500
597
  setTitle(title) {
501
598
  title = title || "";
@@ -526,11 +623,12 @@ export class FreeTransformTool extends Container {
526
623
  }
527
624
  }
528
625
  generateAnchorMark(graphic) {
529
- const anchorInnerRadius = this.controlsSize * 0.125;
530
- const anchorOuterRadius = this.controlsSize * 0.625;
626
+ const scale = 2;
627
+ const anchorInnerRadius = this.controlsSize * 0.125 * scale;
628
+ const anchorOuterRadius = this.controlsSize * 0.625 * scale;
531
629
  graphic
532
630
  .clear()
533
- .circle(0, 0, this.controlsSize * 0.375)
631
+ .circle(0, 0, this.controlsSize * 0.375 * scale)
534
632
  .moveTo(0, anchorInnerRadius)
535
633
  .lineTo(0, anchorOuterRadius)
536
634
  .moveTo(-anchorInnerRadius, 0)
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { FreeTransformTool } from "./FreeTransformTool";
1
+ export { Transformer } from "./FreeTransformTool";
2
2
  export declare function hello(): void;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { FreeTransformTool } from "./FreeTransformTool";
1
+ export { Transformer } from "./FreeTransformTool";
2
2
  export function hello() {
3
3
  console.log("🧩 Hello, from @quinninc/pixi-transformer!");
4
4
  }
package/dist/pixi.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import * as Pixi from "pixi.js";
2
+ export { Pixi };
package/dist/pixi.js ADDED
@@ -0,0 +1,2 @@
1
+ import * as Pixi from "pixi.js";
2
+ export { Pixi };
package/dist/vector.d.ts CHANGED
@@ -1,4 +1,7 @@
1
- import { Point } from "pixi.js";
1
+ type Point = {
2
+ x: number;
3
+ y: number;
4
+ };
2
5
  /**
3
6
  *
4
7
  * @param origin source from where distance will be calculated
@@ -21,3 +24,19 @@ export declare function rotatePoint(point: Point, origin: Point, rotation: numbe
21
24
  export declare function calcDistance(p1: Point, p2: Point): number;
22
25
  export declare function calcAngleDegrees(x: number, y: number): number;
23
26
  export declare function calcAngleRadians(x: number, y: number): number;
27
+ /**
28
+ *
29
+ * @param p point to snap to edges and corners
30
+ * @param snapDistance max distance from edges and corners to trigger snap
31
+ * @param param2 bounds of the rectangle (0,0), (0,width), (width,height), (0, height)
32
+ */
33
+ export declare function snapToEdgesAndCorners({ point, anchor, dim: { width, height }, snapDistance, }: {
34
+ point: Point;
35
+ snapDistance?: number;
36
+ dim: {
37
+ width: number;
38
+ height: number;
39
+ };
40
+ anchor: Point;
41
+ }): Point;
42
+ export {};
package/dist/vector.js CHANGED
@@ -1,4 +1,3 @@
1
- import { Point } from "pixi.js";
2
1
  /**
3
2
  *
4
3
  * @param origin source from where distance will be calculated
@@ -7,8 +6,8 @@ import { Point } from "pixi.js";
7
6
  * @returns 1 for same direction, -1 if the angle is more than 90 degrees
8
7
  */
9
8
  export function getDirection(origin, p1, p2) {
10
- const v1 = new Point(p1.x - origin.x, p1.y - origin.y);
11
- const v2 = new Point(p2.x - origin.x, p2.y - origin.y);
9
+ const v1 = { x: p1.x - origin.x, y: p1.y - origin.y };
10
+ const v2 = { x: p2.x - origin.x, y: p2.y - origin.y };
12
11
  const dot = v1.x * v2.x + v1.y * v2.y;
13
12
  return dot >= 0 ? 1 : -1;
14
13
  }
@@ -27,9 +26,9 @@ export function rotatePoint(point, origin, rotation) {
27
26
  const rotatedX = translatedX * Math.cos(rotation) - translatedY * Math.sin(rotation);
28
27
  const rotatedY = translatedX * Math.sin(rotation) + translatedY * Math.cos(rotation);
29
28
  // Translate point back
30
- const finalX = rotatedX + origin.x;
31
- const finalY = rotatedY + origin.y;
32
- return new Point(finalX, finalY);
29
+ const x = rotatedX + origin.x;
30
+ const y = rotatedY + origin.y;
31
+ return { x, y };
33
32
  }
34
33
  /**
35
34
  * Calculate the euclidean distance between two points.
@@ -43,3 +42,41 @@ export function calcAngleDegrees(x, y) {
43
42
  export function calcAngleRadians(x, y) {
44
43
  return Math.atan2(y, x);
45
44
  }
45
+ /**
46
+ *
47
+ * @param p point to snap to edges and corners
48
+ * @param snapDistance max distance from edges and corners to trigger snap
49
+ * @param param2 bounds of the rectangle (0,0), (0,width), (width,height), (0, height)
50
+ */
51
+ export function snapToEdgesAndCorners({ point, anchor, dim: { width, height }, snapDistance = 10, }) {
52
+ const top = -height * anchor.y;
53
+ const bottom = height + top;
54
+ const left = -width * anchor.x;
55
+ const right = width + left;
56
+ // console.log(top, left, bottom, right);
57
+ // console.log(point);
58
+ const snapPoints = [
59
+ // corners
60
+ { x: left, y: top }, // top-left
61
+ { x: right, y: top }, // top-right
62
+ { x: right, y: bottom }, // bottom-right
63
+ { x: left, y: bottom }, // bottom-left
64
+ // center
65
+ { x: (left + right) / 2, y: (top + bottom) / 2 }, // center
66
+ // edges
67
+ { x: (left + right) / 2, y: top }, // top-edge
68
+ { x: (left + right) / 2, y: bottom }, // bottom-edge
69
+ { x: left, y: (top + bottom) / 2 }, // left-edge
70
+ { x: right, y: (top + bottom) / 2 }, // right-edge
71
+ ];
72
+ let minDistance = Number.MAX_VALUE;
73
+ let snappedPoint = point;
74
+ for (const snapPoint of snapPoints) {
75
+ const distance = calcDistance(point, snapPoint);
76
+ if (distance < snapDistance && distance < minDistance) {
77
+ minDistance = distance;
78
+ snappedPoint = snapPoint;
79
+ }
80
+ }
81
+ return snappedPoint;
82
+ }
package/package.json CHANGED
@@ -1,29 +1,36 @@
1
- {
2
- "name": "@quinninc/pixi-transformer",
3
- "private": false,
4
- "version": "0.0.1",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "module": "dist/index.js",
8
- "types": "dist/index.d.ts",
9
- "files": [
10
- "dist",
11
- "package.json",
12
- "README.md"
13
- ],
14
- "author": {
15
- "name": "Rohit Kaushal",
16
- "url": "https://github.com/RohitKaushal7"
17
- },
18
- "scripts": {
19
- "dev": "tsc -w",
20
- "build": "tsc"
21
- },
22
- "devDependencies": {
23
- "typescript": "^5.2.2",
24
- "vite": "^5.3.1"
25
- },
26
- "dependencies": {
27
- "pixi.js": "^8.2.2"
28
- }
29
- }
1
+ {
2
+ "name": "@quinninc/pixi-transformer",
3
+ "private": false,
4
+ "version": "0.0.3",
5
+ "repository": {
6
+ "url": "https://github.com/Quinn-Care-Private-Limited/pixi-transformer"
7
+ },
8
+ "type": "module",
9
+ "main": "dist/index.js",
10
+ "module": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "files": [
13
+ "dist",
14
+ "package.json",
15
+ "README.md"
16
+ ],
17
+ "author": {
18
+ "name": "Rohit Kaushal",
19
+ "url": "https://github.com/RohitKaushal7"
20
+ },
21
+ "license": "MIT",
22
+ "scripts": {
23
+ "dev": "tsc -w",
24
+ "build": "tsc",
25
+ "deploy": "npm run build && npm version patch && npm publish --access public"
26
+ },
27
+ "devDependencies": {
28
+ "typescript": "^5.2.2",
29
+ "vite": "^5.3.1",
30
+ "pixi.js": "^8.2.1"
31
+ },
32
+ "dependencies": {},
33
+ "peerDependencies": {
34
+ "pixi.js": "^8.2.1"
35
+ }
36
+ }