@quinninc/pixi-transformer 0.0.2 → 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 +61 -65
- package/dist/FreeTransformTool.d.ts +10 -6
- package/dist/FreeTransformTool.js +158 -60
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/pixi.d.ts +2 -0
- package/dist/pixi.js +2 -0
- package/dist/vector.d.ts +20 -1
- package/dist/vector.js +43 -6
- package/package.json +36 -33
package/README.md
CHANGED
|
@@ -1,65 +1,61 @@
|
|
|
1
|
-
# Free Transform Tool for PIXI.js
|
|
2
|
-
|
|
3
|
-
Works with pixi.js v8 and above.
|
|
4
|
-
|
|
5
|
-
;
|
|
28
|
-
app.stage.addChild(root);
|
|
29
|
-
|
|
30
|
-
// create tool and add to stage
|
|
31
|
-
const selectTool = new FreeTransformTool();
|
|
32
|
-
selectTool.label = "transform-tool";
|
|
33
|
-
root.addChild(selectTool);
|
|
34
|
-
|
|
35
|
-
const obj = new Sprite({
|
|
36
|
-
texture: Texture.from("lenna"),
|
|
37
|
-
label: "lenna",
|
|
38
|
-
eventMode: "static",
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
root.addChild(obj);
|
|
42
|
-
|
|
43
|
-
obj.on("pointertap", (ev) => {
|
|
44
|
-
console.log("select - ", ev.currentTarget.label);
|
|
45
|
-
selectTool.select(ev.currentTarget);
|
|
46
|
-
});
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## API
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- `
|
|
58
|
-
- `
|
|
59
|
-
- `
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
**returns:** `PIXI.Container` (the select tool)
|
|
64
|
-
|
|
65
|
-
<!-- INSERT GENERATED DOCS END -->
|
|
1
|
+
# Free Transform Tool for PIXI.js
|
|
2
|
+
|
|
3
|
+
Works with pixi.js v8 and above.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
### ✨ Features
|
|
8
|
+
|
|
9
|
+
- Translate - Drag to move anywhere
|
|
10
|
+
- Scale - Scale on X, Y or both axis'
|
|
11
|
+
- Rotate - drag to rotate
|
|
12
|
+
- Anchor point - update anchor point of transforms (Ctrl + Click)
|
|
13
|
+
- Snapping - hold ctrl to snap rotation at 45degrees, snap anchor point to edges and corners.
|
|
14
|
+
- Theming - custom border color, control size and color, and anchor point graphic
|
|
15
|
+
|
|
16
|
+
> Note - all transformations are applied wrt the pivot point, update pivot point to achieve the desired result.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @quinninc/pixi-transformer
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
const root = new Container();
|
|
28
|
+
app.stage.addChild(root);
|
|
29
|
+
|
|
30
|
+
// create tool and add to stage
|
|
31
|
+
const selectTool = new FreeTransformTool();
|
|
32
|
+
selectTool.label = "transform-tool";
|
|
33
|
+
root.addChild(selectTool);
|
|
34
|
+
|
|
35
|
+
const obj = new Sprite({
|
|
36
|
+
texture: Texture.from("lenna"),
|
|
37
|
+
label: "lenna",
|
|
38
|
+
eventMode: "static",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
root.addChild(obj);
|
|
42
|
+
|
|
43
|
+
obj.on("pointertap", (ev) => {
|
|
44
|
+
console.log("select - ", ev.currentTarget.label);
|
|
45
|
+
selectTool.select(ev.currentTarget);
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## API
|
|
50
|
+
|
|
51
|
+
### `FreeTransformTool` (class)
|
|
52
|
+
|
|
53
|
+
**Constructor Parameter Object:**
|
|
54
|
+
|
|
55
|
+
- `lineColor` - border line color. default - `0x66cfff`
|
|
56
|
+
- `handleColor` - (`number`) - handles' fill color. default - `0xffffff`
|
|
57
|
+
- `controlsSize` - (`number`) - handles' size in pixels. default - `10`
|
|
58
|
+
- `debug` - (`boolean`) - show scaling distance debug lines. default - `false`
|
|
59
|
+
- `generateAnchorMark` - a function to generate your custom anchor mark. default - `undefined` (uses default anchor mark)
|
|
60
|
+
|
|
61
|
+
**returns:** `PIXI.Container` (the select tool)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class
|
|
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<
|
|
76
|
+
get _target(): Pixi.Container<Pixi.ContainerChild> | Pixi.Sprite | null;
|
|
73
77
|
cleanup(): void;
|
|
74
78
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { calcAngleRadians, calcDistance, getDirection, rotatePoint, } from "./vector";
|
|
3
|
-
export class
|
|
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
|
|
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({
|
|
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:
|
|
112
|
-
this.moveHandle.
|
|
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
|
-
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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 =
|
|
362
|
-
handle.
|
|
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
|
-
//
|
|
471
|
+
// console.log("select this - ", this);
|
|
405
472
|
this.target = target;
|
|
406
|
-
|
|
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
|
|
415
|
-
if (target.
|
|
416
|
-
|
|
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
|
-
|
|
515
|
+
_anchor = this._anchor || new Pixi.Point(0.5, 0.5);
|
|
423
516
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
this.
|
|
427
|
-
this.
|
|
428
|
-
this.
|
|
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
|
|
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
|
-
|
|
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
|
|
530
|
-
const
|
|
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 {
|
|
1
|
+
export { Transformer } from "./FreeTransformTool";
|
|
2
2
|
export declare function hello(): void;
|
package/dist/index.js
CHANGED
package/dist/pixi.d.ts
ADDED
package/dist/pixi.js
ADDED
package/dist/vector.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
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 =
|
|
11
|
-
const v2 =
|
|
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
|
|
31
|
-
const
|
|
32
|
-
return
|
|
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,33 +1,36 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@quinninc/pixi-transformer",
|
|
3
|
-
"private": false,
|
|
4
|
-
"version": "0.0.
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
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
|
+
}
|