reacthub-pixitweenjs 0.2.4 → 0.2.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/.storybook/preview.tsx +6 -0
- package/CHANGELOG.md +27 -0
- package/README.md +1 -1
- package/build-storybook.log +79 -476
- package/package.json +29 -29
- package/src/components/PixiAnimatedSprite/PixiAnimatedSprite.tsx +51 -0
- package/src/components/PixiAnimatedSprite/index.ts +2 -0
- package/src/components/PixiAudioSprite/PixiAudioSprite.stories.tsx +61 -0
- package/src/components/PixiAudioSprite/PixiAudioSprite.tsx +202 -0
- package/src/components/PixiAudioSprite/index.ts +1 -0
- package/src/components/PixiGifSprite/PixiGifSprite.stories.tsx +135 -0
- package/src/components/PixiGifSprite/PixiGifSprite.tsx +372 -0
- package/src/components/PixiGifSprite/index.ts +2 -0
- package/src/components/PixiImageSprite/PixiImageSprite.stories.tsx +11 -0
- package/src/components/PixiImageSprite/PixiImageSprite.tsx +33 -70
- package/src/components/PixiSVGSprite/PixiSvgPathSprite.stories.tsx +137 -0
- package/src/components/PixiSVGSprite/PixiSvgPathSprite.tsx +346 -0
- package/src/components/PixiSVGSprite/index.ts +1 -0
- package/src/components/PixiTextSprite/PixiTextSprite.stories.tsx +176 -0
- package/src/components/PixiTextSprite/PixiTextSprite.tsx +540 -0
- package/src/components/PixiTextSprite/index.ts +1 -0
- package/src/components/PixiVideoSprite/PixiVideoSprite.stories.tsx +147 -0
- package/src/components/PixiVideoSprite/PixiVideoSprite.tsx +631 -0
- package/src/components/PixiVideoSprite/PixiVideoSpriteBackup.txt +755 -0
- package/src/components/PixiVideoSprite/index.ts +1 -0
- package/src/declare.module.ts +5 -0
- package/src/main.tsx +8 -7
- package/src/providers/GsapPixieContextProvider.tsx +102 -22
- package/src/reacthub-react-bindings.d.ts +27 -0
- package/src/stories/Installation.mdx +3 -3
- package/src/utils/AppStateProvider.tsx +18 -29
- package/src/utils/AppStateStage.tsx +1 -13
- package/src/utils/AppWrapper.tsx +4 -0
- package/src/utils/GsapAnim.tsx +1 -7
- package/src/utils/InteractionManager.tsx +36 -0
- package/src/utils/PixiStage.tsx +1 -5
- package/src/utils/PixiTransformer.tsx +165 -0
- package/src/utils/VideoSeekBar.tsx +35 -31
- package/src/utils/useDebounce.tsx +15 -0
- package/src/hooks/usePixiTransformer.tsx +0 -168
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PixiVideoSprite } from "./PixiVideoSprite";
|
package/src/main.tsx
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import ReactDOM from
|
|
3
|
-
import App from
|
|
4
|
-
import
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as ReactDOM from "react-dom/client";
|
|
3
|
+
import App from "./App";
|
|
4
|
+
import "./index.css";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
ReactDOM.createRoot(document.getElementById("root")).render(
|
|
7
8
|
<React.StrictMode>
|
|
8
9
|
<App />
|
|
9
|
-
</React.StrictMode
|
|
10
|
-
)
|
|
10
|
+
</React.StrictMode>
|
|
11
|
+
);
|
|
@@ -7,18 +7,23 @@ import {
|
|
|
7
7
|
useLayoutEffect,
|
|
8
8
|
} from "react";
|
|
9
9
|
import gsap from "gsap";
|
|
10
|
-
import { emitCustomEvent } from "react-custom-events";
|
|
10
|
+
import { emitCustomEvent, useCustomEventListener } from "react-custom-events";
|
|
11
|
+
import { useDebounce } from "../utils/useDebounce";
|
|
11
12
|
|
|
12
13
|
interface GsapPixieContextProps {
|
|
13
14
|
gsapCtx: React.MutableRefObject<any>;
|
|
14
15
|
tl: React.MutableRefObject<any>;
|
|
16
|
+
play: boolean;
|
|
17
|
+
isDragging: boolean;
|
|
15
18
|
handlePlay: () => void;
|
|
16
19
|
handlePause: () => void;
|
|
17
20
|
handleReset: () => void;
|
|
18
|
-
handleSeek: () => void;
|
|
21
|
+
handleSeek: (value: number) => void;
|
|
22
|
+
handleSeekTest: () => void;
|
|
19
23
|
handleRestart: () => void;
|
|
20
24
|
handleRepeat: () => void;
|
|
21
25
|
playerTimeRef: React.MutableRefObject<number>;
|
|
26
|
+
totalDuration: number;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
// Context has been created
|
|
@@ -30,6 +35,12 @@ const Events = {
|
|
|
30
35
|
PAUSE: "GSAP_PAUSE",
|
|
31
36
|
PLAY: "GSAP_PLAY",
|
|
32
37
|
RESUME: "GSAP_RESUME",
|
|
38
|
+
RESTART: "GSAP_RESTART",
|
|
39
|
+
REPEAT: "GSAP_REPEAT",
|
|
40
|
+
SEEK: "GSAP_SEEK",
|
|
41
|
+
RESET: "GSAP_RESET",
|
|
42
|
+
DRAGGING_START: "GSAP_DRAGGING_START",
|
|
43
|
+
DRAGGING_END: "GSAP_DRAGGING_END",
|
|
33
44
|
};
|
|
34
45
|
|
|
35
46
|
// Provider
|
|
@@ -37,15 +48,18 @@ const GsapPixieContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
37
48
|
children,
|
|
38
49
|
}) => {
|
|
39
50
|
const [play, setPlay] = useState<boolean>(false);
|
|
40
|
-
const [
|
|
51
|
+
const [isDragging, setIsDragging] = useState<boolean>(false);
|
|
52
|
+
const [internalDuration, setInternalDuration] = useState<number>(0);
|
|
53
|
+
const [totalDuration, setTotalDuration] = useState<number>(0);
|
|
54
|
+
const delayedDuration = useDebounce(internalDuration, 600);
|
|
41
55
|
|
|
42
56
|
const tl = useRef<any>();
|
|
43
57
|
const gsapCtx = useRef<any>();
|
|
44
58
|
const playerTimeRef = useRef<number>(0.001);
|
|
45
59
|
|
|
46
|
-
const parentElementRef = useRef<any>();
|
|
60
|
+
// const parentElementRef = useRef<any>();
|
|
47
61
|
// передаем предка анимируемых элементов
|
|
48
|
-
const q = gsap.utils.selector(parentElementRef);
|
|
62
|
+
// const q = gsap.utils.selector(parentElementRef);
|
|
49
63
|
|
|
50
64
|
useLayoutEffect(() => {
|
|
51
65
|
gsapCtx.current = gsap.context(() => {
|
|
@@ -60,29 +74,72 @@ const GsapPixieContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
60
74
|
return () => gsapCtx.current.revert();
|
|
61
75
|
}, []);
|
|
62
76
|
|
|
77
|
+
gsap.ticker.add(() => {
|
|
78
|
+
// console.log("timeframe", time, deltaTime, frame);
|
|
79
|
+
// setFrameNumber(frame);
|
|
80
|
+
if (tl.current && getTimelineDuration) {
|
|
81
|
+
setInternalDuration(getTimelineDuration());
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
63
85
|
const onUpdate = useCallback(() => {
|
|
64
86
|
/// console.log("update event callback");
|
|
65
87
|
const timeline = tl.current;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (playerTimeRef.current) {
|
|
69
|
-
|
|
70
|
-
}
|
|
88
|
+
let now = timeline.time();
|
|
89
|
+
// let elapsedTime;
|
|
90
|
+
// if (playerTimeRef.current) {
|
|
91
|
+
// elapsedTime = now - playerTimeRef.current;
|
|
92
|
+
// }
|
|
71
93
|
// console.log(`elapseTime :${elapsedTime} and frame: ${frameNumber}`);
|
|
72
94
|
//time = now;
|
|
73
95
|
playerTimeRef.current = now;
|
|
74
96
|
}, []);
|
|
75
97
|
|
|
98
|
+
// set the total duration based on the delayed duration value
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
setTotalDuration(delayedDuration);
|
|
101
|
+
}, [delayedDuration]);
|
|
102
|
+
|
|
76
103
|
useEffect(() => {
|
|
77
104
|
const timeline = tl.current;
|
|
78
105
|
timeline
|
|
106
|
+
.eventCallback("onStart", function () {
|
|
107
|
+
// console.log("onstart", timeline.progress());
|
|
108
|
+
// setPlay(true);
|
|
109
|
+
// onUpdate();
|
|
110
|
+
})
|
|
111
|
+
.eventCallback("onInterrupt", function () {
|
|
112
|
+
/// console.log("onInterrupt", timeline.progress());
|
|
113
|
+
setPlay(false);
|
|
114
|
+
onUpdate();
|
|
115
|
+
})
|
|
79
116
|
.eventCallback("onUpdate", function () {
|
|
80
117
|
/// console.log("onupdate", timeline.progress());
|
|
81
118
|
onUpdate();
|
|
82
119
|
})
|
|
120
|
+
// .eventCallback("onRepeat", function () {
|
|
121
|
+
// /// console.log("onrepeat", timeline.progress());
|
|
122
|
+
// onUpdate();
|
|
123
|
+
// })
|
|
124
|
+
// .eventCallback("onReverseComplete", function () {
|
|
125
|
+
// /// console.log("onReverseComplete", timeline.progress());
|
|
126
|
+
// onUpdate();
|
|
127
|
+
// })
|
|
128
|
+
// write a pause event
|
|
129
|
+
.eventCallback("onPause", function () {
|
|
130
|
+
console.log("onPause", timeline.progress());
|
|
131
|
+
setPlay(false);
|
|
132
|
+
onUpdate();
|
|
133
|
+
})
|
|
134
|
+
.eventCallback("onResume", function () {
|
|
135
|
+
console.log("onResume", timeline.progress());
|
|
136
|
+
setPlay(true);
|
|
137
|
+
onUpdate();
|
|
138
|
+
})
|
|
83
139
|
.eventCallback("onComplete", function () {
|
|
84
|
-
timeline.seek(0
|
|
140
|
+
timeline.seek(0);
|
|
85
141
|
timeline.pause();
|
|
142
|
+
setPlay(false);
|
|
86
143
|
onUpdate();
|
|
87
144
|
});
|
|
88
145
|
}, []);
|
|
@@ -96,11 +153,6 @@ const GsapPixieContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
96
153
|
}
|
|
97
154
|
}, [play]);
|
|
98
155
|
|
|
99
|
-
const addTotalDuration = (duration: number) => {
|
|
100
|
-
const timeline = tl.current;
|
|
101
|
-
timeline.totalDuration(duration);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
156
|
const handleReset = useCallback(() => {
|
|
105
157
|
const timeline = tl.current;
|
|
106
158
|
|
|
@@ -110,39 +162,63 @@ const GsapPixieContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
110
162
|
const handleRestart = useCallback(() => {
|
|
111
163
|
const timeline = tl.current;
|
|
112
164
|
timeline.restart();
|
|
165
|
+
setPlay(true);
|
|
113
166
|
}, []);
|
|
114
167
|
|
|
115
168
|
const handleRepeat = useCallback(() => {
|
|
116
169
|
const timeline = tl.current;
|
|
117
|
-
|
|
118
170
|
timeline.repeat(1);
|
|
119
171
|
timeline.restart();
|
|
172
|
+
// setPlay(true);
|
|
120
173
|
}, []);
|
|
121
174
|
|
|
122
|
-
const handleSeek = useCallback(() => {
|
|
175
|
+
const handleSeek = useCallback((value: number) => {
|
|
123
176
|
const timeline = tl.current;
|
|
124
|
-
timeline.seek(
|
|
177
|
+
timeline.seek(value);
|
|
125
178
|
}, []);
|
|
126
179
|
|
|
127
|
-
const
|
|
180
|
+
const handleSeekTest = useCallback(() => {
|
|
128
181
|
const timeline = tl.current;
|
|
182
|
+
timeline.seek(4);
|
|
183
|
+
}, []);
|
|
184
|
+
|
|
185
|
+
// const setTimelineDuration = useCallback(() => {
|
|
186
|
+
// const timeline = tl.current;
|
|
187
|
+
// timeline.totalDuration(3);
|
|
188
|
+
// }, []);
|
|
129
189
|
|
|
130
|
-
|
|
190
|
+
const getTimelineDuration = useCallback(() => {
|
|
191
|
+
const timeline = tl.current;
|
|
192
|
+
if (!timeline) return 0;
|
|
193
|
+
return timeline.totalDuration();
|
|
131
194
|
}, []);
|
|
132
195
|
|
|
133
196
|
const handlePause = () => {
|
|
134
197
|
const timeline = tl.current;
|
|
135
|
-
|
|
136
198
|
timeline.pause();
|
|
137
199
|
emitCustomEvent(Events.PAUSE);
|
|
200
|
+
setPlay(false);
|
|
138
201
|
};
|
|
139
202
|
|
|
140
203
|
const handlePlay = () => {
|
|
141
204
|
const timeline = tl.current;
|
|
205
|
+
setPlay(true);
|
|
142
206
|
timeline.resume();
|
|
143
207
|
emitCustomEvent(Events.RESUME);
|
|
144
208
|
};
|
|
145
209
|
|
|
210
|
+
/** Event listener dragging */
|
|
211
|
+
useCustomEventListener(Events.DRAGGING_START, () => {
|
|
212
|
+
console.log("dragging start");
|
|
213
|
+
setIsDragging(true);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
useCustomEventListener(Events.DRAGGING_END, () => {
|
|
217
|
+
setIsDragging(false);
|
|
218
|
+
console.log("dragging end");
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
console.log("set play updated", play);
|
|
146
222
|
return (
|
|
147
223
|
<GsapPixieContext.Provider
|
|
148
224
|
value={{
|
|
@@ -152,9 +228,13 @@ const GsapPixieContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
152
228
|
handlePause,
|
|
153
229
|
handleReset,
|
|
154
230
|
handleSeek,
|
|
231
|
+
handleSeekTest,
|
|
155
232
|
handleRestart,
|
|
156
233
|
handleRepeat,
|
|
157
234
|
playerTimeRef,
|
|
235
|
+
play,
|
|
236
|
+
totalDuration,
|
|
237
|
+
isDragging,
|
|
158
238
|
}}
|
|
159
239
|
>
|
|
160
240
|
{children}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as PIXI from "pixi.js";
|
|
3
|
+
|
|
4
|
+
declare module "reacthub-react-bindings" {
|
|
5
|
+
interface TransformerProps {
|
|
6
|
+
group: PIXI.DisplayObject[];
|
|
7
|
+
rotateEnabled?: boolean;
|
|
8
|
+
boxRotationEnabled?: boolean;
|
|
9
|
+
boxScalingEnabled?: boolean;
|
|
10
|
+
wireframeStyle?: {
|
|
11
|
+
thickness: number;
|
|
12
|
+
color: number;
|
|
13
|
+
};
|
|
14
|
+
lockAspectRatio?: boolean;
|
|
15
|
+
scaleEnabled?: boolean;
|
|
16
|
+
handleStyle?: {
|
|
17
|
+
color?: number;
|
|
18
|
+
outlineColor?: number;
|
|
19
|
+
shape?: "circle" | "square";
|
|
20
|
+
radius?: number;
|
|
21
|
+
};
|
|
22
|
+
transformchange?: (transform: PIXI.Matrix) => void;
|
|
23
|
+
transformcommit?: (transform: PIXI.Matrix) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class Transformer extends React.Component<TransformerProps> {}
|
|
27
|
+
}
|
|
@@ -8,19 +8,6 @@ interface AppState {
|
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
interface AppStateContextProps extends AppState {
|
|
12
|
-
onAnchorTransformationEnd: (data: TransformationEnd) => void;
|
|
13
|
-
onMouseOverSprite: (data: unknown) => void;
|
|
14
|
-
onClickSprite: (data: unknown) => void;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const AppStateContext = React.createContext<AppStateContextProps>({
|
|
18
|
-
transformation: {},
|
|
19
|
-
onAnchorTransformationEnd: () => {},
|
|
20
|
-
onMouseOverSprite: () => {},
|
|
21
|
-
onClickSprite: () => {},
|
|
22
|
-
});
|
|
23
|
-
|
|
24
11
|
interface AppStateContextProviderProps extends AppState {
|
|
25
12
|
children: React.ReactNode;
|
|
26
13
|
}
|
|
@@ -28,43 +15,45 @@ interface AppStateContextProviderProps extends AppState {
|
|
|
28
15
|
export const AppStateContextProvider: React.FC<
|
|
29
16
|
AppStateContextProviderProps
|
|
30
17
|
> = ({ children, ...props }) => {
|
|
18
|
+
console.log("AppStateContextProvider", props);
|
|
31
19
|
const [appState, setAppState] = React.useState<AppState>(props);
|
|
20
|
+
const appStateRef = React.useRef<AppState>(appState);
|
|
21
|
+
|
|
32
22
|
useDeepEffect(() => {
|
|
33
23
|
setAppState(props);
|
|
24
|
+
appStateRef.current = props;
|
|
34
25
|
}, [props]);
|
|
35
26
|
|
|
36
27
|
const onAnchorTransformationEnd = React.useCallback(
|
|
37
|
-
(data: {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}) => {
|
|
41
|
-
const { uniqueId, transformation } = data;
|
|
28
|
+
(data: TransformationEnd) => {
|
|
29
|
+
console.log("onAnchorTransformationEnd", data);
|
|
30
|
+
const { transformation } = data;
|
|
42
31
|
const newAppState = {
|
|
43
|
-
...
|
|
32
|
+
...appStateRef.current,
|
|
44
33
|
transformation: {
|
|
45
|
-
...
|
|
34
|
+
...appStateRef.current?.transformation,
|
|
46
35
|
...transformation,
|
|
47
36
|
},
|
|
48
37
|
};
|
|
38
|
+
console.log("saving state", newAppState);
|
|
49
39
|
setAppState(newAppState);
|
|
50
40
|
},
|
|
51
|
-
[
|
|
41
|
+
[]
|
|
52
42
|
);
|
|
53
43
|
|
|
54
|
-
const onMouseOverSprite = React.useCallback((
|
|
44
|
+
const onMouseOverSprite = React.useCallback(() => {}, []);
|
|
55
45
|
|
|
56
|
-
const onClickSprite = React.useCallback((
|
|
46
|
+
const onClickSprite = React.useCallback(() => {}, []);
|
|
57
47
|
|
|
58
48
|
return (
|
|
59
|
-
|
|
60
|
-
|
|
49
|
+
<>
|
|
50
|
+
{/*@ts-ignore */}
|
|
51
|
+
{React.cloneElement(children, {
|
|
61
52
|
...appState,
|
|
62
53
|
onAnchorTransformationEnd,
|
|
63
54
|
onMouseOverSprite,
|
|
64
55
|
onClickSprite,
|
|
65
|
-
}}
|
|
66
|
-
|
|
67
|
-
{children}
|
|
68
|
-
</AppStateContext.Provider>
|
|
56
|
+
})}
|
|
57
|
+
</>
|
|
69
58
|
);
|
|
70
59
|
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import ContextBridge from "./ContextBridge";
|
|
3
|
-
import { AppStateContext } from "../providers/AppStateProvider";
|
|
4
2
|
import { Container as PixiContainer } from "@pixi/react";
|
|
5
3
|
|
|
6
4
|
interface AppStateStageProps {
|
|
@@ -11,17 +9,7 @@ const AppStateStage: React.FC<AppStateStageProps> = ({
|
|
|
11
9
|
children,
|
|
12
10
|
...props
|
|
13
11
|
}) => {
|
|
14
|
-
return
|
|
15
|
-
<ContextBridge
|
|
16
|
-
Context={AppStateContext}
|
|
17
|
-
render={(children: React.ReactNode) => (
|
|
18
|
-
// @ts-ignore
|
|
19
|
-
<PixiContainer {...props}>{children}</PixiContainer>
|
|
20
|
-
)}
|
|
21
|
-
>
|
|
22
|
-
{children}
|
|
23
|
-
</ContextBridge>
|
|
24
|
-
);
|
|
12
|
+
return <PixiContainer {...props}>{children}</PixiContainer>;
|
|
25
13
|
};
|
|
26
14
|
|
|
27
15
|
export default AppStateStage;
|
package/src/utils/AppWrapper.tsx
CHANGED
|
@@ -18,9 +18,13 @@ export const AppWrapper: React.FC<AppProps> = ({
|
|
|
18
18
|
const backgroundColorx = PIXI.utils.string2hex(backgroundColor || "#2D2E3C");
|
|
19
19
|
const width = 600;
|
|
20
20
|
const height = 500;
|
|
21
|
+
const quillEditorRef = React.useRef<HTMLDivElement>(null);
|
|
22
|
+
|
|
21
23
|
/// color: 0x1099bb,
|
|
22
24
|
return (
|
|
23
25
|
<div className="App">
|
|
26
|
+
<div id="note-editor" ref={quillEditorRef}></div>
|
|
27
|
+
<div id="lottieroot"></div>
|
|
24
28
|
<GsapPixieContextProvider>
|
|
25
29
|
<ChakraProvider>
|
|
26
30
|
<Flex flexDir={"column"}>
|
package/src/utils/GsapAnim.tsx
CHANGED
|
@@ -26,13 +26,7 @@ interface Ease {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export const getAnimByName = (
|
|
30
|
-
animate: string,
|
|
31
|
-
stageWidth?: number,
|
|
32
|
-
stageHeight?: number,
|
|
33
|
-
x?: number,
|
|
34
|
-
y?: number,
|
|
35
|
-
): Ease => {
|
|
29
|
+
export const getAnimByName = (animate: string): Ease => {
|
|
36
30
|
let ease: Ease = {};
|
|
37
31
|
switch (animate) {
|
|
38
32
|
case "NONE":
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useApp } from "@pixi/react";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
|
|
4
|
+
type PixiInteractionManagerProps = {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
options?: {
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const interactionManagerSettings = { moveWhenInside: true };
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Initialize Pixi Interaction Manager
|
|
15
|
+
* @param param0
|
|
16
|
+
* @returns
|
|
17
|
+
* @see https://pixijs.download/dev/docs/PIXI.InteractionManager.html
|
|
18
|
+
* @see https://pixijs.download/dev/docs/PIXI.InteractionManager.html#moveWhenInside
|
|
19
|
+
* @see https://pixijs.download/dev/docs/PIXI.InteractionManager.html#on
|
|
20
|
+
*
|
|
21
|
+
* */
|
|
22
|
+
const InteractionManager = ({
|
|
23
|
+
children,
|
|
24
|
+
options = interactionManagerSettings,
|
|
25
|
+
}: PixiInteractionManagerProps) => {
|
|
26
|
+
const app = useApp();
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
Object.keys(options).forEach((key) => {
|
|
30
|
+
app.renderer.plugins.interaction[key] = options[key];
|
|
31
|
+
});
|
|
32
|
+
}, [options]);
|
|
33
|
+
|
|
34
|
+
return children;
|
|
35
|
+
};
|
|
36
|
+
export default InteractionManager;
|
package/src/utils/PixiStage.tsx
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import ContextBridge from "./ContextBridge";
|
|
3
3
|
import { Stage as PixiStage } from "@pixi/react";
|
|
4
|
-
import { AppStateContextProvider } from "./AppStateProvider";
|
|
5
4
|
import { GsapPixieContext } from "../providers/GsapPixieContextProvider";
|
|
6
5
|
|
|
7
6
|
interface StageProps {
|
|
@@ -18,10 +17,7 @@ const Stage: React.FC<StageProps> = ({ children, ...props }) => {
|
|
|
18
17
|
render={(children: React.ReactNode | React.ReactElement) => (
|
|
19
18
|
<PixiStage {...props}>
|
|
20
19
|
{/* @ts-ignore */}
|
|
21
|
-
|
|
22
|
-
{/* @ts-ignore */}
|
|
23
|
-
{children}
|
|
24
|
-
</AppStateContextProvider>
|
|
20
|
+
{children}
|
|
25
21
|
</PixiStage>
|
|
26
22
|
)}
|
|
27
23
|
>
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import * as PIXI from "pixi.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import { Transformer } from "reacthub-react-bindings";
|
|
5
|
+
|
|
6
|
+
type PixiTransformerProps = {
|
|
7
|
+
pixiTransformerRef: React.MutableRefObject<any>;
|
|
8
|
+
imageRef: React.MutableRefObject<any>;
|
|
9
|
+
isMounted: boolean;
|
|
10
|
+
transformCommit?: (data: any) => void;
|
|
11
|
+
transformChange?: (data: any) => void;
|
|
12
|
+
mouseoverEvent?: (flag: boolean) => void;
|
|
13
|
+
onDoubleClick?: (data: any) => void;
|
|
14
|
+
uniqueId?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type PixiTransformerState = {
|
|
18
|
+
isDragging: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initialize PixiTransformer to transform the image
|
|
23
|
+
* @param param0
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
const PixiTransformer = ({
|
|
27
|
+
pixiTransformerRef,
|
|
28
|
+
imageRef,
|
|
29
|
+
isMounted,
|
|
30
|
+
transformCommit,
|
|
31
|
+
transformChange,
|
|
32
|
+
mouseoverEvent,
|
|
33
|
+
onDoubleClick,
|
|
34
|
+
uniqueId = "",
|
|
35
|
+
}: PixiTransformerProps) => {
|
|
36
|
+
// states
|
|
37
|
+
const colorYellow = PIXI.utils.string2hex("#F3C409");
|
|
38
|
+
const anchorFill = PIXI.utils.string2hex("#F3C409");
|
|
39
|
+
const transformerState = React.useRef<PixiTransformerState>({
|
|
40
|
+
isDragging: false,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const handleOnMouseOver = React.useCallback(() => {
|
|
44
|
+
if (mouseoverEvent && !transformerState.current.isDragging) {
|
|
45
|
+
mouseoverEvent(true);
|
|
46
|
+
}
|
|
47
|
+
}, [mouseoverEvent]);
|
|
48
|
+
|
|
49
|
+
const handleOnMouseOut = React.useCallback(() => {
|
|
50
|
+
if (mouseoverEvent && !transformerState.current.isDragging) {
|
|
51
|
+
mouseoverEvent(false);
|
|
52
|
+
}
|
|
53
|
+
}, [mouseoverEvent]);
|
|
54
|
+
|
|
55
|
+
const handleOnMouseDown = React.useCallback(() => {
|
|
56
|
+
// update transfomer state to is draggin.
|
|
57
|
+
transformerState.current.isDragging = true;
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
const handleOnMouseUp = React.useCallback(() => {
|
|
61
|
+
// update transfomer state to is not dragging.
|
|
62
|
+
transformerState.current.isDragging = false;
|
|
63
|
+
}, []);
|
|
64
|
+
|
|
65
|
+
const handleOnMouseUpOutside = React.useCallback(() => {
|
|
66
|
+
// update transfomer state to is not dragging.
|
|
67
|
+
transformerState.current.isDragging = false;
|
|
68
|
+
}, []);
|
|
69
|
+
|
|
70
|
+
const handleOnDoubleClick = React.useCallback(() => {
|
|
71
|
+
console.log("dobule click in pixi transformer");
|
|
72
|
+
if (onDoubleClick) onDoubleClick({ uniqueId });
|
|
73
|
+
}, [onDoubleClick]);
|
|
74
|
+
|
|
75
|
+
// add handler for transform change
|
|
76
|
+
const handleOnTransformChange = React.useCallback(
|
|
77
|
+
(e: any) => {
|
|
78
|
+
// update transfomer state to is draggin.
|
|
79
|
+
transformerState.current.isDragging = true;
|
|
80
|
+
if (transformChange) transformChange(e);
|
|
81
|
+
},
|
|
82
|
+
[transformChange]
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const handleOnTransformCommit = React.useCallback(() => {
|
|
86
|
+
if (imageRef.current === null) return;
|
|
87
|
+
const x = imageRef.current.x;
|
|
88
|
+
const y = imageRef.current.y;
|
|
89
|
+
const width = imageRef.current.width;
|
|
90
|
+
const height = imageRef.current.height;
|
|
91
|
+
const rotate = imageRef.current.rotation;
|
|
92
|
+
const scale: [number, number] = [
|
|
93
|
+
imageRef.current.scale.x,
|
|
94
|
+
imageRef.current.scale.y,
|
|
95
|
+
];
|
|
96
|
+
if (transformCommit) {
|
|
97
|
+
transformCommit({
|
|
98
|
+
uniqueId,
|
|
99
|
+
transformation: {
|
|
100
|
+
x: Math.round(x),
|
|
101
|
+
y: Math.round(y),
|
|
102
|
+
width: Math.round(Math.max(5, width)),
|
|
103
|
+
height: Math.round(Math.max(5, height)),
|
|
104
|
+
rotate: Math.round(rotate),
|
|
105
|
+
scale: scale,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// update transformer state to is not dragging.
|
|
110
|
+
transformerState.current.isDragging = false;
|
|
111
|
+
}, [transformCommit]);
|
|
112
|
+
|
|
113
|
+
React.useEffect(() => {
|
|
114
|
+
if (pixiTransformerRef.current) {
|
|
115
|
+
pixiTransformerRef.current.on("mouseover", handleOnMouseOver);
|
|
116
|
+
pixiTransformerRef.current.on("mouseout", handleOnMouseOut);
|
|
117
|
+
pixiTransformerRef.current.on("mousedown", handleOnMouseDown);
|
|
118
|
+
pixiTransformerRef.current.on("mouseup", handleOnMouseUp);
|
|
119
|
+
pixiTransformerRef.current.on("mouseupoutside", handleOnMouseUpOutside);
|
|
120
|
+
/// pixiTransformerRef.current.on("dblclick", handleOnDoubleClick);
|
|
121
|
+
pixiTransformerRef.current.addListener("dblclick", handleOnDoubleClick);
|
|
122
|
+
}
|
|
123
|
+
return () => {
|
|
124
|
+
if (pixiTransformerRef.current) {
|
|
125
|
+
pixiTransformerRef.current.off("mouseover", handleOnMouseOver);
|
|
126
|
+
pixiTransformerRef.current.off("mouseout", handleOnMouseOut);
|
|
127
|
+
pixiTransformerRef.current.off("mousedown", handleOnMouseDown);
|
|
128
|
+
pixiTransformerRef.current.off("mouseup", handleOnMouseUp);
|
|
129
|
+
pixiTransformerRef.current.off(
|
|
130
|
+
"mouseupoutside",
|
|
131
|
+
handleOnMouseUpOutside
|
|
132
|
+
);
|
|
133
|
+
//// pixiTransformerRef.current.off("dblclick", handleOnDoubleClick);
|
|
134
|
+
pixiTransformerRef.current.removeListener(
|
|
135
|
+
"dblclick",
|
|
136
|
+
handleOnDoubleClick
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}, []);
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<Transformer
|
|
144
|
+
ref={pixiTransformerRef}
|
|
145
|
+
group={isMounted ? [imageRef.current] : []}
|
|
146
|
+
rotateEnabled={true}
|
|
147
|
+
boxRotationEnabled={true}
|
|
148
|
+
centeredScaling={true}
|
|
149
|
+
boxScalingEnabled={true}
|
|
150
|
+
wireframeStyle={{ thickness: 1, color: anchorFill }}
|
|
151
|
+
lockAspectRatio={true}
|
|
152
|
+
scaleEnabled={true}
|
|
153
|
+
handleStyle={{
|
|
154
|
+
// color: colorYellow,
|
|
155
|
+
outlineColor: colorYellow,
|
|
156
|
+
shape: "circle",
|
|
157
|
+
radius: 9,
|
|
158
|
+
}}
|
|
159
|
+
transformchange={handleOnTransformChange}
|
|
160
|
+
transformcommit={handleOnTransformCommit}
|
|
161
|
+
/>
|
|
162
|
+
);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export default PixiTransformer;
|