@quinninc/pixi-transformer 0.0.4 → 0.0.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.
- package/README.md +61 -61
- package/dist/FreeTransformTool.d.ts +6 -10
- package/dist/FreeTransformTool.js +61 -159
- package/dist/Transformer.d.ts +80 -0
- package/dist/Transformer.js +668 -0
- package/dist/graphics.d.ts +52 -0
- package/dist/graphics.js +115 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/vector.d.ts +1 -20
- package/dist/vector.js +6 -43
- package/package.json +41 -41
package/README.md
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
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
|
+
# 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,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class
|
|
1
|
+
import { Container, Graphics, Sprite } from "pixi.js";
|
|
2
|
+
export declare class FreeTransformTool extends Container {
|
|
3
3
|
private debug;
|
|
4
|
-
private id;
|
|
5
4
|
private moveHandle;
|
|
6
5
|
private rotateHandle;
|
|
7
6
|
private scaleTHandle;
|
|
@@ -28,7 +27,6 @@ export declare class Transformer extends Pixi.Container {
|
|
|
28
27
|
private top;
|
|
29
28
|
private bottom;
|
|
30
29
|
private right;
|
|
31
|
-
private _anchor;
|
|
32
30
|
private dragging;
|
|
33
31
|
/**
|
|
34
32
|
*
|
|
@@ -53,26 +51,24 @@ export declare class Transformer extends Pixi.Container {
|
|
|
53
51
|
*
|
|
54
52
|
* selectTool.unselect();
|
|
55
53
|
*/
|
|
56
|
-
constructor({
|
|
57
|
-
id?: string;
|
|
54
|
+
constructor({ lineColor, handleColor, controlsSize, debug, generateAnchorMark, }?: {
|
|
58
55
|
lineColor?: string | number;
|
|
59
56
|
handleColor?: string | number;
|
|
60
57
|
controlsSize?: number;
|
|
61
58
|
debug?: boolean;
|
|
62
|
-
generateAnchorMark?: false | ((graphic:
|
|
59
|
+
generateAnchorMark?: false | ((graphic: Graphics) => void);
|
|
63
60
|
});
|
|
64
61
|
private addToolTip;
|
|
65
62
|
private handleHandleEvents;
|
|
66
63
|
private createHandle;
|
|
67
64
|
private createHandleIndicatorTo;
|
|
68
65
|
private deScale;
|
|
69
|
-
select(target:
|
|
70
|
-
onUpdate: () => void;
|
|
66
|
+
select(target: Container): void;
|
|
71
67
|
unselect(): void;
|
|
72
68
|
update(): void;
|
|
73
69
|
setTitle(title: string): void;
|
|
74
70
|
setCursor(cursor: string): void;
|
|
75
71
|
private generateAnchorMark;
|
|
76
|
-
get _target():
|
|
72
|
+
get _target(): Container<import("pixi.js").ContainerChild> | Sprite | null;
|
|
77
73
|
cleanup(): void;
|
|
78
74
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { calcAngleRadians, calcDistance, getDirection, rotatePoint,
|
|
3
|
-
export class
|
|
1
|
+
import { Container, Graphics, Point, Rectangle, } from "pixi.js";
|
|
2
|
+
import { calcAngleRadians, calcDistance, getDirection, rotatePoint, } from "./vector";
|
|
3
|
+
export class FreeTransformTool extends Container {
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
6
6
|
* @param p.lineColor - border line color
|
|
@@ -24,20 +24,17 @@ export class Transformer extends Pixi.Container {
|
|
|
24
24
|
*
|
|
25
25
|
* selectTool.unselect();
|
|
26
26
|
*/
|
|
27
|
-
constructor({
|
|
27
|
+
constructor({ lineColor = 0x66cfff, handleColor = 0xffffff, controlsSize = 10, debug = false, generateAnchorMark, } = {}) {
|
|
28
28
|
super();
|
|
29
|
-
// target
|
|
29
|
+
// target 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);
|
|
37
36
|
this.dragging = false;
|
|
38
|
-
this.onUpdate = () => { };
|
|
39
37
|
const that = this;
|
|
40
|
-
this.id = id;
|
|
41
38
|
this.debug = debug;
|
|
42
39
|
this.lineColor = lineColor;
|
|
43
40
|
this.handleColor = handleColor;
|
|
@@ -51,24 +48,21 @@ export class Transformer extends Pixi.Container {
|
|
|
51
48
|
else if (generateAnchorMark === false)
|
|
52
49
|
this.generateAnchorMark = () => { };
|
|
53
50
|
this.zIndex = 1e7;
|
|
54
|
-
//
|
|
51
|
+
// Container Properties
|
|
55
52
|
this.visible = false;
|
|
56
53
|
// create border
|
|
57
|
-
this.border = new
|
|
54
|
+
this.border = new Graphics({ label: "Border" });
|
|
58
55
|
this.addChild(this.border);
|
|
59
56
|
// Anchor mark
|
|
60
|
-
this.anchorMark = new
|
|
61
|
-
label: "AnchorMark",
|
|
62
|
-
eventMode: "none",
|
|
63
|
-
});
|
|
57
|
+
this.anchorMark = new Graphics({ label: "AnchorMark" });
|
|
64
58
|
this.anchorMark.alpha = this.handleOpacity;
|
|
65
59
|
this.addChild(this.anchorMark);
|
|
66
60
|
// debug indicators
|
|
67
|
-
this.fromPoint = new
|
|
61
|
+
this.fromPoint = new Graphics({
|
|
68
62
|
label: "fromPoint",
|
|
69
63
|
alpha: this.handleOpacity * 0.75,
|
|
70
64
|
});
|
|
71
|
-
this.toPoint = new
|
|
65
|
+
this.toPoint = new Graphics({
|
|
72
66
|
label: "toPoint",
|
|
73
67
|
alpha: this.handleOpacity * 0.75,
|
|
74
68
|
});
|
|
@@ -114,65 +108,20 @@ export class Transformer extends Pixi.Container {
|
|
|
114
108
|
});
|
|
115
109
|
this.addChild(this.scaleTHandle, this.scaleRHandle, this.scaleBHandle, this.scaleLHandle, this.scaleTLHandle, this.scaleTRHandle, this.scaleBRHandle, this.scaleBLHandle, this.rotateHandle);
|
|
116
110
|
// ------------<MoveTool>---------------
|
|
117
|
-
this.moveHandle = new
|
|
118
|
-
this.moveHandle.
|
|
111
|
+
this.moveHandle = new Graphics({ label: "moveHandle" });
|
|
112
|
+
this.moveHandle.interactive = true;
|
|
119
113
|
this.addToolTip(this.moveHandle, "Move", "move");
|
|
120
114
|
this.moveHandle
|
|
121
115
|
.on("pointerdown", onMoveHandleDown)
|
|
122
116
|
.on("pointerup", onMoveHandleUp)
|
|
123
117
|
.on("pointerupoutside", onMoveHandleUp);
|
|
124
118
|
this.handleHandleEvents(this.moveHandle, this);
|
|
125
|
-
this.moveHandle.hitArea = new
|
|
119
|
+
this.moveHandle.hitArea = new Rectangle(0, 0, this.controlsSize, this.controlsSize);
|
|
126
120
|
this.addChild(this.moveHandle);
|
|
127
|
-
function changeAnchorPoint(ev) {
|
|
128
|
-
// console.log("TAPP this, that - ", this, that);
|
|
129
|
-
if (!ev.ctrlKey && !ev.metaKey)
|
|
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
|
-
}
|
|
169
121
|
function onMoveHandleDown(downEvent) {
|
|
170
122
|
// console.log("onMoveHandleDown this, that - ", this, that);
|
|
171
123
|
if (!that.target)
|
|
172
124
|
return;
|
|
173
|
-
if (downEvent.ctrlKey || downEvent.metaKey) {
|
|
174
|
-
this.draggingPivot = true;
|
|
175
|
-
}
|
|
176
125
|
// data
|
|
177
126
|
this.targetStartPos = that.target.position.clone();
|
|
178
127
|
this.dragDistance = 0;
|
|
@@ -182,24 +131,7 @@ export class Transformer extends Pixi.Container {
|
|
|
182
131
|
// console.log("onMoveHandleMove this, that - ", this, that);
|
|
183
132
|
if (!this.dragging || !that.target)
|
|
184
133
|
return;
|
|
185
|
-
|
|
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);
|
|
134
|
+
const moveDelta = new Point(moveEvent.global.x - this.eventStartGlobalPos.x, moveEvent.global.y - this.eventStartGlobalPos.y);
|
|
203
135
|
that.target.position.x = this.targetStartPos.x + moveDelta.x;
|
|
204
136
|
that.target.position.y = this.targetStartPos.y + moveDelta.y;
|
|
205
137
|
this.dragDistance = calcDistance(moveEvent.global, this.eventStartGlobalPos);
|
|
@@ -209,11 +141,12 @@ export class Transformer extends Pixi.Container {
|
|
|
209
141
|
function onMoveHandleUp(upEvent) {
|
|
210
142
|
// console.log("onMoveHandleUp this, that - ", this, that);
|
|
211
143
|
upEvent.stopPropagation();
|
|
212
|
-
if
|
|
213
|
-
|
|
214
|
-
|
|
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();
|
|
215
149
|
}
|
|
216
|
-
this.draggingPivot = false;
|
|
217
150
|
this.off("globalpointermove", onMoveHandleMove);
|
|
218
151
|
}
|
|
219
152
|
// ------------</ MoveTool>---------------
|
|
@@ -242,7 +175,7 @@ export class Transformer extends Pixi.Container {
|
|
|
242
175
|
return;
|
|
243
176
|
const distStart = calcDistance(this.eventStartGlobalPos, that.target.position);
|
|
244
177
|
const distEnd = calcDistance(moveEvent.global, that.target.position);
|
|
245
|
-
const direction = getDirection(new
|
|
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));
|
|
246
179
|
this.rescaleFactor = (distEnd / distStart) * direction;
|
|
247
180
|
that.target.scale.x = this.targetStartScale.x * this.rescaleFactor;
|
|
248
181
|
that.target.scale.y = this.targetStartScale.y * this.rescaleFactor;
|
|
@@ -348,7 +281,7 @@ export class Transformer extends Pixi.Container {
|
|
|
348
281
|
const endAngle = calcAngleRadians(relativeEndPoint.x, relativeEndPoint.y);
|
|
349
282
|
const deltaAngle = endAngle - startAngle;
|
|
350
283
|
let finalRotation = this.targetStartRotation + deltaAngle;
|
|
351
|
-
if (moveEvent.ctrlKey
|
|
284
|
+
if (moveEvent.ctrlKey) {
|
|
352
285
|
const snapAngle = 45;
|
|
353
286
|
let finalAngle = (finalRotation * 180) / Math.PI;
|
|
354
287
|
const proximity = Math.min(Math.abs(finalAngle % snapAngle), snapAngle - Math.abs(finalAngle % snapAngle));
|
|
@@ -424,9 +357,9 @@ export class Transformer extends Pixi.Container {
|
|
|
424
357
|
.on("pointerupoutside", onHandleUp);
|
|
425
358
|
}
|
|
426
359
|
createHandle({ cursor, name, shape = "square", }) {
|
|
427
|
-
const handle = new
|
|
428
|
-
handle.label =
|
|
429
|
-
handle.
|
|
360
|
+
const handle = new Graphics();
|
|
361
|
+
handle.label = name;
|
|
362
|
+
handle.interactive = true;
|
|
430
363
|
handle.alpha = this.handleOpacity;
|
|
431
364
|
this.addToolTip(handle, name, cursor);
|
|
432
365
|
if (shape === "circle") {
|
|
@@ -444,8 +377,8 @@ export class Transformer extends Pixi.Container {
|
|
|
444
377
|
createHandleIndicatorTo(handle, x, y) {
|
|
445
378
|
x = x - this.position.x;
|
|
446
379
|
y = y - this.position.y;
|
|
447
|
-
const p1 = new
|
|
448
|
-
const origin = new
|
|
380
|
+
const p1 = new Point(x, y);
|
|
381
|
+
const origin = new Point(0, 0);
|
|
449
382
|
const p = rotatePoint(p1, origin, -this.rotation);
|
|
450
383
|
x = p.x;
|
|
451
384
|
y = p.y;
|
|
@@ -468,62 +401,35 @@ export class Transformer extends Pixi.Container {
|
|
|
468
401
|
this.unselect();
|
|
469
402
|
return;
|
|
470
403
|
}
|
|
471
|
-
// console.log("select this - ", this);
|
|
472
|
-
this.target = target;
|
|
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
404
|
// copy object translation/transformation
|
|
501
|
-
|
|
405
|
+
this.target = target;
|
|
406
|
+
const bounds = target.getLocalBounds();
|
|
502
407
|
this.width = bounds.width;
|
|
503
408
|
this.height = bounds.height;
|
|
504
|
-
this.scale.x =
|
|
505
|
-
this.scale.y =
|
|
506
|
-
this.x =
|
|
507
|
-
this.y =
|
|
508
|
-
this.rotation =
|
|
509
|
-
let
|
|
510
|
-
if (
|
|
511
|
-
|
|
512
|
-
|
|
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);
|
|
513
420
|
}
|
|
514
421
|
else {
|
|
515
|
-
|
|
422
|
+
anchor = new Point(0.5, 0.5);
|
|
516
423
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
this.
|
|
520
|
-
this.
|
|
521
|
-
this.
|
|
522
|
-
this.right = bounds.width * (1 - _anchor.x);
|
|
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);
|
|
523
429
|
// anchor mark
|
|
524
430
|
this.generateAnchorMark?.(this.anchorMark);
|
|
525
431
|
this.deScale(this.anchorMark);
|
|
526
|
-
|
|
432
|
+
this.anchorMark.rotation = -this.rotation;
|
|
527
433
|
const rotationHandlePos = {
|
|
528
434
|
x: (this.left + this.right) / 2,
|
|
529
435
|
y: this.top - 80 / Math.abs(this.scale.y),
|
|
@@ -554,21 +460,7 @@ export class Transformer extends Pixi.Container {
|
|
|
554
460
|
color: this.lineColor,
|
|
555
461
|
});
|
|
556
462
|
// draw move hit area
|
|
557
|
-
|
|
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);
|
|
463
|
+
this.moveHandle.hitArea = new Rectangle(this.left, this.top, bounds.width, bounds.height);
|
|
572
464
|
this.scaleTLHandle.position.set(this.left, this.top);
|
|
573
465
|
this.scaleTRHandle.position.set(this.right, this.top);
|
|
574
466
|
this.scaleBRHandle.position.set(this.right, this.bottom);
|
|
@@ -593,6 +485,17 @@ export class Transformer extends Pixi.Container {
|
|
|
593
485
|
allHandles.forEach((handle) => {
|
|
594
486
|
this.deScale(handle);
|
|
595
487
|
});
|
|
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
|
+
}
|
|
596
499
|
}
|
|
597
500
|
setTitle(title) {
|
|
598
501
|
title = title || "";
|
|
@@ -623,12 +526,11 @@ export class Transformer extends Pixi.Container {
|
|
|
623
526
|
}
|
|
624
527
|
}
|
|
625
528
|
generateAnchorMark(graphic) {
|
|
626
|
-
const
|
|
627
|
-
const
|
|
628
|
-
const anchorOuterRadius = this.controlsSize * 0.625 * scale;
|
|
529
|
+
const anchorInnerRadius = this.controlsSize * 0.125;
|
|
530
|
+
const anchorOuterRadius = this.controlsSize * 0.625;
|
|
629
531
|
graphic
|
|
630
532
|
.clear()
|
|
631
|
-
.circle(0, 0, this.controlsSize * 0.375
|
|
533
|
+
.circle(0, 0, this.controlsSize * 0.375)
|
|
632
534
|
.moveTo(0, anchorInnerRadius)
|
|
633
535
|
.lineTo(0, anchorOuterRadius)
|
|
634
536
|
.moveTo(-anchorInnerRadius, 0)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Pixi } from "./pixi";
|
|
2
|
+
export declare class Transformer extends Pixi.Container {
|
|
3
|
+
private debug;
|
|
4
|
+
private _id;
|
|
5
|
+
private moveHandle;
|
|
6
|
+
private rotateHandle;
|
|
7
|
+
private scaleTHandle;
|
|
8
|
+
private scaleRHandle;
|
|
9
|
+
private scaleBHandle;
|
|
10
|
+
private scaleLHandle;
|
|
11
|
+
private scaleTLHandle;
|
|
12
|
+
private scaleTRHandle;
|
|
13
|
+
private scaleBRHandle;
|
|
14
|
+
private scaleBLHandle;
|
|
15
|
+
private border;
|
|
16
|
+
private anchorMark;
|
|
17
|
+
private fromPoint;
|
|
18
|
+
private toPoint;
|
|
19
|
+
private target;
|
|
20
|
+
private movedThreshold;
|
|
21
|
+
private handleOpacity;
|
|
22
|
+
private controlsSize;
|
|
23
|
+
private controlsDimOpacity;
|
|
24
|
+
private controlsStrokeThickness;
|
|
25
|
+
private lineColor;
|
|
26
|
+
private handleColor;
|
|
27
|
+
private left;
|
|
28
|
+
private top;
|
|
29
|
+
private bottom;
|
|
30
|
+
private right;
|
|
31
|
+
private _anchor;
|
|
32
|
+
private dragging;
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @param p.lineColor - border line color
|
|
36
|
+
* @param p.handleColor - handles' fill color
|
|
37
|
+
* @param p.controlsSize - handles' size in pixels
|
|
38
|
+
* @param p.debug - show scaling distance debug lines
|
|
39
|
+
* @param p.generateAnchorMark - a function to generate your custom anchor mark
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* const selectTool = new FreeTransformTool({
|
|
43
|
+
* lineColor: 0x66cfff,
|
|
44
|
+
* handleColor: 0xffffff,
|
|
45
|
+
* controlsSize: 10,
|
|
46
|
+
* debug: false,
|
|
47
|
+
* generateAnchorMark: (g) => g.clear().circle(0,0,10).fill(0xff0000); // please use clear() to clear the geometry first every time. leave undefined for default anchor mark. set false to disable.
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* root.addChild(selectTool); // by default the tool has a z-index of 1e7 (10000000). you can change it according to your requirement
|
|
51
|
+
*
|
|
52
|
+
* selectTool.select(obj);
|
|
53
|
+
*
|
|
54
|
+
* selectTool.unselect();
|
|
55
|
+
*/
|
|
56
|
+
constructor({ id, lineColor, handleColor, controlsSize, debug, generateAnchorMark, }?: {
|
|
57
|
+
id?: string;
|
|
58
|
+
lineColor?: string | number;
|
|
59
|
+
handleColor?: string | number;
|
|
60
|
+
controlsSize?: number;
|
|
61
|
+
debug?: boolean;
|
|
62
|
+
generateAnchorMark?: false | ((graphic: Pixi.Graphics) => void);
|
|
63
|
+
});
|
|
64
|
+
private addToolTip;
|
|
65
|
+
private handleHandleEvents;
|
|
66
|
+
private createHandle;
|
|
67
|
+
private createHandleIndicatorTo;
|
|
68
|
+
private deScale;
|
|
69
|
+
select(target: Pixi.Container): void;
|
|
70
|
+
unselect(): void;
|
|
71
|
+
onUpdate: () => void;
|
|
72
|
+
update(): void;
|
|
73
|
+
setTitle(title: string): void;
|
|
74
|
+
setCursor(cursor: string): void;
|
|
75
|
+
private generateAnchorMark;
|
|
76
|
+
get _target(): Pixi.Container<Pixi.ContainerChild> | Pixi.Sprite | null;
|
|
77
|
+
get id(): string;
|
|
78
|
+
cleanup(): void;
|
|
79
|
+
private convertToLocal;
|
|
80
|
+
}
|