reacthub-pixitweenjs 0.2.3 → 0.2.5
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/{main.js → main.ts} +9 -1
- package/.storybook/{preview.jsx → preview.tsx} +3 -7
- package/CHANGELOG.md +40 -0
- package/README.md +21 -2
- package/build-storybook.log +94 -0
- package/index.html +1 -1
- package/package.json +68 -36
- package/src/App.tsx +29 -0
- 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 +212 -0
- package/src/components/PixiAudioSprite/index.ts +1 -0
- package/src/components/PixiGifSprite/PixiGifSprite.stories.tsx +135 -0
- package/src/components/PixiGifSprite/PixiGifSprite.tsx +451 -0
- package/src/components/PixiGifSprite/index.ts +2 -0
- package/src/{stories/PixiImageSprite/PixiImageSprite.stories.js → components/PixiImageSprite/PixiImageSprite.stories.tsx} +36 -8
- package/src/components/PixiImageSprite/PixiImageSprite.tsx +340 -0
- package/src/components/PixiImageSprite/index.ts +1 -0
- package/src/components/PixiSVGSprite/PixiSvgPathSprite.stories.tsx +137 -0
- package/src/components/PixiSVGSprite/PixiSvgPathSprite.tsx +378 -0
- package/src/components/PixiSVGSprite/index.ts +1 -0
- package/src/components/PixiVideoSprite/PixiVideoSprite.stories.tsx +147 -0
- package/src/components/PixiVideoSprite/PixiVideoSprite.tsx +684 -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/hooks/usePixiTransformer.tsx +168 -0
- package/src/index.ts +3 -0
- package/src/providers/GsapPixieContextProvider.tsx +251 -0
- package/src/providers/index.ts +1 -0
- package/src/reacthub-react-bindings.d.ts +27 -0
- package/src/types/transformation.tsx +13 -0
- package/src/utils/AppStateProvider.tsx +59 -0
- package/src/utils/AppStateStage.tsx +27 -0
- package/src/utils/AppWrapper.tsx +43 -0
- package/src/utils/ContextBridge.tsx +25 -0
- package/src/{providers/GsapAnim.jsx → utils/GsapAnim.tsx} +35 -4
- package/src/utils/PixiStage.tsx +29 -0
- package/src/utils/PixiTransformer.tsx +100 -0
- package/src/utils/VideoSeekBar.tsx +129 -0
- package/src/utils/useDebounce.tsx +15 -0
- package/src/utils/useDeepEffect.tsx +23 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +37 -0
- package/tsconfig.node.json +10 -0
- package/{vite.config.js → vite.config.ts} +4 -2
- package/vitest.config.ts +11 -0
- package/src/App.jsx +0 -35
- package/src/index.js +0 -3
- package/src/providers/ContextBridge.jsx +0 -67
- package/src/providers/GsapPixieContextProvider.jsx +0 -162
- package/src/providers/VideoSeekBar.jsx +0 -186
- package/src/providers/index.js +0 -3
- package/src/stories/PixiImageSprite/PixiImageSprite.jsx +0 -318
- package/src/stories/PixiImageSprite/index.js +0 -1
- /package/src/{main.jsx → main.tsx} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PixiVideoSprite } from "./PixiVideoSprite";
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Transformer } from "@pixi-essentials/transformer";
|
|
2
|
+
import * as PIXI from "pixi.js";
|
|
3
|
+
import { useApp } from "@pixi/react";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { useEffect, useRef, useCallback } from "react";
|
|
6
|
+
import { Transformation } from "../types/transformation";
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
import has from "lodash/has";
|
|
9
|
+
|
|
10
|
+
const colorYellow = PIXI.utils.string2hex("#F3C409");
|
|
11
|
+
const anchorFill = PIXI.utils.string2hex("#F3C409");
|
|
12
|
+
|
|
13
|
+
interface Events {
|
|
14
|
+
dblclick?: (e: any) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface Props {
|
|
18
|
+
uniqueId?: string;
|
|
19
|
+
onTransformEnd?: (data: {
|
|
20
|
+
uniqueId: string;
|
|
21
|
+
transformation: Transformation;
|
|
22
|
+
}) => void;
|
|
23
|
+
events?: Events;
|
|
24
|
+
mouseoverEvent?: (flag: boolean) => void;
|
|
25
|
+
setDragging?: (flag: boolean) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const usePixiTransformer = ({
|
|
29
|
+
uniqueId = "",
|
|
30
|
+
onTransformEnd,
|
|
31
|
+
events = {},
|
|
32
|
+
mouseoverEvent = (f) => f,
|
|
33
|
+
setDragging = (f) => f,
|
|
34
|
+
}: Props) => {
|
|
35
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
36
|
+
const PixiTransformer = React.useRef<PIXI.Container>(null);
|
|
37
|
+
const mounted = React.useRef(false);
|
|
38
|
+
const app = useApp();
|
|
39
|
+
const transformerRef = useRef<Transformer>(null);
|
|
40
|
+
const parentRef = useRef<PIXI.Container>(null);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
mounted.current = true;
|
|
44
|
+
return () => {
|
|
45
|
+
mounted.current = false;
|
|
46
|
+
if (transformerRef.current) {
|
|
47
|
+
parentRef.current?.removeChild(transformerRef.current);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
const transformChange = useCallback(() => {
|
|
53
|
+
setIsDragging(true);
|
|
54
|
+
setDragging(true);
|
|
55
|
+
}, []);
|
|
56
|
+
|
|
57
|
+
const transformCommit = useCallback(() => {
|
|
58
|
+
if (PixiTransformer.current === null) return;
|
|
59
|
+
const x = PixiTransformer.current.x;
|
|
60
|
+
const y = PixiTransformer.current.y;
|
|
61
|
+
const width = PixiTransformer.current.width;
|
|
62
|
+
const height = PixiTransformer.current.height;
|
|
63
|
+
const rotate = PixiTransformer.current.rotation;
|
|
64
|
+
const scale: [number, number] = [
|
|
65
|
+
PixiTransformer.current.scale.x,
|
|
66
|
+
PixiTransformer.current.scale.y,
|
|
67
|
+
];
|
|
68
|
+
if (onTransformEnd) {
|
|
69
|
+
onTransformEnd({
|
|
70
|
+
uniqueId,
|
|
71
|
+
transformation: {
|
|
72
|
+
x: Math.round(x),
|
|
73
|
+
y: Math.round(y),
|
|
74
|
+
width: Math.round(Math.max(5, width)),
|
|
75
|
+
height: Math.round(Math.max(5, height)),
|
|
76
|
+
rotate: Math.round(rotate),
|
|
77
|
+
scale: scale,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
setIsDragging(false);
|
|
82
|
+
setDragging(false);
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
85
|
+
const handleOnDblClick = useCallback((e: any) => {
|
|
86
|
+
if (events && has(events, "dblclick") && events.dblclick) {
|
|
87
|
+
events.dblclick(e);
|
|
88
|
+
}
|
|
89
|
+
}, []);
|
|
90
|
+
|
|
91
|
+
const handleOnMouseOver = useCallback(
|
|
92
|
+
(msevent: any) => {
|
|
93
|
+
if (mouseoverEvent) {
|
|
94
|
+
mouseoverEvent(true);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
[mouseoverEvent],
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const handleOnMouseOut = useCallback(
|
|
101
|
+
(msevent: any) => {
|
|
102
|
+
if (mouseoverEvent) {
|
|
103
|
+
mouseoverEvent(false);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
[mouseoverEvent],
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const handleTransformer = useCallback(
|
|
110
|
+
(node: PIXI.Container, parentNode: PIXI.Container) => {
|
|
111
|
+
const isEnabled = true;
|
|
112
|
+
// @ts-ignore
|
|
113
|
+
PixiTransformer.current = node;
|
|
114
|
+
const transformer = new Transformer({
|
|
115
|
+
rotateEnabled: isEnabled,
|
|
116
|
+
boxRotationEnabled: isEnabled,
|
|
117
|
+
boxScalingEnabled: isEnabled,
|
|
118
|
+
scaleEnabled: isEnabled,
|
|
119
|
+
group: [node],
|
|
120
|
+
wireframeStyle: {
|
|
121
|
+
thickness: 2,
|
|
122
|
+
color: anchorFill,
|
|
123
|
+
},
|
|
124
|
+
lockAspectRatio: true,
|
|
125
|
+
handleStyle: {
|
|
126
|
+
// color: colorYellow,
|
|
127
|
+
outlineColor: colorYellow,
|
|
128
|
+
shape: "circle",
|
|
129
|
+
radius: 10,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// transformer.addListener("transformchange", transformChange);
|
|
134
|
+
// @ts-ignore
|
|
135
|
+
transformer.addListener("transformcommit", transformCommit);
|
|
136
|
+
// transformer.addListener("dblclick", (evt) => {
|
|
137
|
+
// handleOnDblClick(evt);
|
|
138
|
+
// });
|
|
139
|
+
// transformer.on("mouseover", () => {
|
|
140
|
+
// handleOnMouseOver(true);
|
|
141
|
+
// });
|
|
142
|
+
// transformer.on("mouseout", () => {
|
|
143
|
+
// handleOnMouseOut(false);
|
|
144
|
+
// });
|
|
145
|
+
// @ts-ignore
|
|
146
|
+
transformerRef.current = transformer;
|
|
147
|
+
// @ts-ignore
|
|
148
|
+
parentRef.current = parentNode;
|
|
149
|
+
parentRef.current.addChild(transformerRef.current);
|
|
150
|
+
},
|
|
151
|
+
[
|
|
152
|
+
transformCommit,
|
|
153
|
+
transformChange,
|
|
154
|
+
handleOnMouseOver,
|
|
155
|
+
handleOnMouseOut,
|
|
156
|
+
handleOnDblClick,
|
|
157
|
+
],
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
const removeTransformer = useCallback(() => {
|
|
161
|
+
if (transformerRef.current) {
|
|
162
|
+
// @ts-ignore
|
|
163
|
+
parentRef.current.removeChild(transformerRef.current);
|
|
164
|
+
}
|
|
165
|
+
}, []);
|
|
166
|
+
|
|
167
|
+
return { handleTransformer, removeTransformer, isDragging };
|
|
168
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import {
|
|
3
|
+
useState,
|
|
4
|
+
useEffect,
|
|
5
|
+
useCallback,
|
|
6
|
+
useRef,
|
|
7
|
+
useLayoutEffect,
|
|
8
|
+
} from "react";
|
|
9
|
+
import gsap from "gsap";
|
|
10
|
+
import { emitCustomEvent, useCustomEventListener } from "react-custom-events";
|
|
11
|
+
import { useDebounce } from "../utils/useDebounce";
|
|
12
|
+
|
|
13
|
+
interface GsapPixieContextProps {
|
|
14
|
+
gsapCtx: React.MutableRefObject<any>;
|
|
15
|
+
tl: React.MutableRefObject<any>;
|
|
16
|
+
play: boolean;
|
|
17
|
+
isDragging: boolean;
|
|
18
|
+
handlePlay: () => void;
|
|
19
|
+
handlePause: () => void;
|
|
20
|
+
handleReset: () => void;
|
|
21
|
+
handleSeek: (value: number) => void;
|
|
22
|
+
handleSeekTest: () => void;
|
|
23
|
+
handleRestart: () => void;
|
|
24
|
+
handleRepeat: () => void;
|
|
25
|
+
playerTimeRef: React.MutableRefObject<number>;
|
|
26
|
+
totalDuration: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Context has been created
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
const GsapPixieContext = React.createContext<GsapPixieContextProps>({});
|
|
32
|
+
|
|
33
|
+
const Events = {
|
|
34
|
+
STOP: "GSAP_STOP",
|
|
35
|
+
PAUSE: "GSAP_PAUSE",
|
|
36
|
+
PLAY: "GSAP_PLAY",
|
|
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",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Provider
|
|
47
|
+
const GsapPixieContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
48
|
+
children,
|
|
49
|
+
}) => {
|
|
50
|
+
const [play, setPlay] = useState<boolean>(false);
|
|
51
|
+
const [frameNumber, setFrameNumber] = useState<number>(0);
|
|
52
|
+
const [isDragging, setIsDragging] = useState<boolean>(false);
|
|
53
|
+
const [internalDuration, setInternalDuration] = useState<number>(0);
|
|
54
|
+
const [totalDuration, setTotalDuration] = useState<number>(0);
|
|
55
|
+
const delayedDuration = useDebounce(internalDuration, 600);
|
|
56
|
+
|
|
57
|
+
const tl = useRef<any>();
|
|
58
|
+
const gsapCtx = useRef<any>();
|
|
59
|
+
const playerTimeRef = useRef<number>(0.001);
|
|
60
|
+
|
|
61
|
+
const parentElementRef = useRef<any>();
|
|
62
|
+
// передаем предка анимируемых элементов
|
|
63
|
+
const q = gsap.utils.selector(parentElementRef);
|
|
64
|
+
|
|
65
|
+
useLayoutEffect(() => {
|
|
66
|
+
gsapCtx.current = gsap.context(() => {
|
|
67
|
+
// add a box and circle animation to our timeline and play on first render
|
|
68
|
+
// console.log("creating timeline");
|
|
69
|
+
tl.current && tl.current.progress(0).kill();
|
|
70
|
+
tl.current = gsap.timeline({
|
|
71
|
+
paused: true,
|
|
72
|
+
defaults: { duration: 0 },
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
return () => gsapCtx.current.revert();
|
|
76
|
+
}, []);
|
|
77
|
+
|
|
78
|
+
gsap.ticker.add((time, deltaTime, frame) => {
|
|
79
|
+
// console.log("timeframe", time, deltaTime, frame);
|
|
80
|
+
// setFrameNumber(frame);
|
|
81
|
+
if (tl.current && getTimelineDuration) {
|
|
82
|
+
setInternalDuration(getTimelineDuration());
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const onUpdate = useCallback(() => {
|
|
87
|
+
/// console.log("update event callback");
|
|
88
|
+
const timeline = tl.current;
|
|
89
|
+
var now = timeline.time();
|
|
90
|
+
var elapsedTime;
|
|
91
|
+
if (playerTimeRef.current) {
|
|
92
|
+
elapsedTime = now - playerTimeRef.current;
|
|
93
|
+
}
|
|
94
|
+
// console.log(`elapseTime :${elapsedTime} and frame: ${frameNumber}`);
|
|
95
|
+
//time = now;
|
|
96
|
+
playerTimeRef.current = now;
|
|
97
|
+
}, []);
|
|
98
|
+
|
|
99
|
+
// set the total duration based on the delayed duration value
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
setTotalDuration(delayedDuration);
|
|
102
|
+
}, [delayedDuration]);
|
|
103
|
+
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
const timeline = tl.current;
|
|
106
|
+
timeline
|
|
107
|
+
.eventCallback("onStart", function () {
|
|
108
|
+
// console.log("onstart", timeline.progress());
|
|
109
|
+
// setPlay(true);
|
|
110
|
+
// onUpdate();
|
|
111
|
+
})
|
|
112
|
+
.eventCallback("onInterrupt", function () {
|
|
113
|
+
/// console.log("onInterrupt", timeline.progress());
|
|
114
|
+
setPlay(false);
|
|
115
|
+
onUpdate();
|
|
116
|
+
})
|
|
117
|
+
.eventCallback("onUpdate", function () {
|
|
118
|
+
/// console.log("onupdate", timeline.progress());
|
|
119
|
+
onUpdate();
|
|
120
|
+
})
|
|
121
|
+
// .eventCallback("onRepeat", function () {
|
|
122
|
+
// /// console.log("onrepeat", timeline.progress());
|
|
123
|
+
// onUpdate();
|
|
124
|
+
// })
|
|
125
|
+
// .eventCallback("onReverseComplete", function () {
|
|
126
|
+
// /// console.log("onReverseComplete", timeline.progress());
|
|
127
|
+
// onUpdate();
|
|
128
|
+
// })
|
|
129
|
+
// write a pause event
|
|
130
|
+
.eventCallback("onPause", function () {
|
|
131
|
+
console.log("onPause", timeline.progress());
|
|
132
|
+
setPlay(false);
|
|
133
|
+
onUpdate();
|
|
134
|
+
})
|
|
135
|
+
.eventCallback("onResume", function () {
|
|
136
|
+
console.log("onResume", timeline.progress());
|
|
137
|
+
setPlay(true);
|
|
138
|
+
onUpdate();
|
|
139
|
+
})
|
|
140
|
+
.eventCallback("onComplete", function () {
|
|
141
|
+
timeline.seek(0);
|
|
142
|
+
timeline.pause();
|
|
143
|
+
setPlay(false);
|
|
144
|
+
onUpdate();
|
|
145
|
+
});
|
|
146
|
+
}, []);
|
|
147
|
+
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
const timeline = tl.current;
|
|
150
|
+
if (!play) {
|
|
151
|
+
timeline.pause();
|
|
152
|
+
} else {
|
|
153
|
+
timeline.resume();
|
|
154
|
+
}
|
|
155
|
+
}, [play]);
|
|
156
|
+
|
|
157
|
+
const addTotalDuration = (duration: number) => {
|
|
158
|
+
const timeline = tl.current;
|
|
159
|
+
timeline.totalDuration(duration);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const handleReset = useCallback(() => {
|
|
163
|
+
const timeline = tl.current;
|
|
164
|
+
|
|
165
|
+
timeline.revert();
|
|
166
|
+
}, []);
|
|
167
|
+
|
|
168
|
+
const handleRestart = useCallback(() => {
|
|
169
|
+
const timeline = tl.current;
|
|
170
|
+
timeline.restart();
|
|
171
|
+
setPlay(true);
|
|
172
|
+
}, []);
|
|
173
|
+
|
|
174
|
+
const handleRepeat = useCallback(() => {
|
|
175
|
+
const timeline = tl.current;
|
|
176
|
+
timeline.repeat(1);
|
|
177
|
+
timeline.restart();
|
|
178
|
+
// setPlay(true);
|
|
179
|
+
}, []);
|
|
180
|
+
|
|
181
|
+
const handleSeek = useCallback((value: number) => {
|
|
182
|
+
const timeline = tl.current;
|
|
183
|
+
timeline.seek(value);
|
|
184
|
+
}, []);
|
|
185
|
+
|
|
186
|
+
const handleSeekTest = useCallback(() => {
|
|
187
|
+
const timeline = tl.current;
|
|
188
|
+
timeline.seek(4);
|
|
189
|
+
}, []);
|
|
190
|
+
|
|
191
|
+
const setTimelineDuration = useCallback(() => {
|
|
192
|
+
const timeline = tl.current;
|
|
193
|
+
timeline.totalDuration(3);
|
|
194
|
+
}, []);
|
|
195
|
+
|
|
196
|
+
const getTimelineDuration = useCallback(() => {
|
|
197
|
+
const timeline = tl.current;
|
|
198
|
+
if (!timeline) return 0;
|
|
199
|
+
return timeline.totalDuration();
|
|
200
|
+
}, []);
|
|
201
|
+
|
|
202
|
+
const handlePause = () => {
|
|
203
|
+
const timeline = tl.current;
|
|
204
|
+
timeline.pause();
|
|
205
|
+
emitCustomEvent(Events.PAUSE);
|
|
206
|
+
setPlay(false);
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const handlePlay = () => {
|
|
210
|
+
const timeline = tl.current;
|
|
211
|
+
setPlay(true);
|
|
212
|
+
timeline.resume();
|
|
213
|
+
emitCustomEvent(Events.RESUME);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/** Event listener dragging */
|
|
217
|
+
useCustomEventListener(Events.DRAGGING_START, (time) => {
|
|
218
|
+
console.log("dragging start");
|
|
219
|
+
setIsDragging(true);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
useCustomEventListener(Events.DRAGGING_END, (time) => {
|
|
223
|
+
setIsDragging(false);
|
|
224
|
+
console.log("dragging end");
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
console.log("set play updated", play);
|
|
228
|
+
return (
|
|
229
|
+
<GsapPixieContext.Provider
|
|
230
|
+
value={{
|
|
231
|
+
gsapCtx,
|
|
232
|
+
tl,
|
|
233
|
+
handlePlay,
|
|
234
|
+
handlePause,
|
|
235
|
+
handleReset,
|
|
236
|
+
handleSeek,
|
|
237
|
+
handleSeekTest,
|
|
238
|
+
handleRestart,
|
|
239
|
+
handleRepeat,
|
|
240
|
+
playerTimeRef,
|
|
241
|
+
play,
|
|
242
|
+
totalDuration,
|
|
243
|
+
isDragging,
|
|
244
|
+
}}
|
|
245
|
+
>
|
|
246
|
+
{children}
|
|
247
|
+
</GsapPixieContext.Provider>
|
|
248
|
+
);
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
export { GsapPixieContext, GsapPixieContextProvider, Events };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./GsapPixieContextProvider";
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import useDeepEffect from "./useDeepEffect";
|
|
3
|
+
import { TransformationEnd } from "../types/transformation";
|
|
4
|
+
|
|
5
|
+
interface AppState {
|
|
6
|
+
transformation: {
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface AppStateContextProviderProps extends AppState {
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const AppStateContextProvider: React.FC<
|
|
16
|
+
AppStateContextProviderProps
|
|
17
|
+
> = ({ children, ...props }) => {
|
|
18
|
+
console.log("AppStateContextProvider", props);
|
|
19
|
+
const [appState, setAppState] = React.useState<AppState>(props);
|
|
20
|
+
const appStateRef = React.useRef<AppState>(appState);
|
|
21
|
+
|
|
22
|
+
useDeepEffect(() => {
|
|
23
|
+
setAppState(props);
|
|
24
|
+
appStateRef.current = props;
|
|
25
|
+
}, [props]);
|
|
26
|
+
|
|
27
|
+
const onAnchorTransformationEnd = React.useCallback(
|
|
28
|
+
(data: TransformationEnd) => {
|
|
29
|
+
console.log("onAnchorTransformationEnd", data);
|
|
30
|
+
const { uniqueId, transformation } = data;
|
|
31
|
+
const newAppState = {
|
|
32
|
+
...appStateRef.current,
|
|
33
|
+
transformation: {
|
|
34
|
+
...appStateRef.current?.transformation,
|
|
35
|
+
...transformation,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
console.log("saving state", newAppState);
|
|
39
|
+
setAppState(newAppState);
|
|
40
|
+
},
|
|
41
|
+
[]
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const onMouseOverSprite = React.useCallback((data: unknown) => {}, []);
|
|
45
|
+
|
|
46
|
+
const onClickSprite = React.useCallback((data: unknown) => {}, []);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
{/*@ts-ignore */}
|
|
51
|
+
{React.cloneElement(children, {
|
|
52
|
+
...appState,
|
|
53
|
+
onAnchorTransformationEnd,
|
|
54
|
+
onMouseOverSprite,
|
|
55
|
+
onClickSprite,
|
|
56
|
+
})}
|
|
57
|
+
</>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import ContextBridge from "./ContextBridge";
|
|
3
|
+
import { AppStateContext } from "./AppStateProvider";
|
|
4
|
+
import { Container as PixiContainer } from "@pixi/react";
|
|
5
|
+
|
|
6
|
+
interface AppStateStageProps {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const AppStateStage: React.FC<AppStateStageProps> = ({
|
|
11
|
+
children,
|
|
12
|
+
...props
|
|
13
|
+
}) => {
|
|
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
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default AppStateStage;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Flex, Box } from "@chakra-ui/react";
|
|
3
|
+
import * as PIXI from "pixi.js";
|
|
4
|
+
import { ChakraProvider } from "@chakra-ui/react";
|
|
5
|
+
import { GsapPixieContextProvider } from "../providers/GsapPixieContextProvider";
|
|
6
|
+
import { VideoSeekBar } from "./VideoSeekBar";
|
|
7
|
+
import Stage from "./PixiStage";
|
|
8
|
+
|
|
9
|
+
interface AppProps {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
backgroundColor?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const AppWrapper: React.FC<AppProps> = ({
|
|
15
|
+
children,
|
|
16
|
+
backgroundColor,
|
|
17
|
+
}) => {
|
|
18
|
+
const backgroundColorx = PIXI.utils.string2hex(backgroundColor || "#2D2E3C");
|
|
19
|
+
const width = 600;
|
|
20
|
+
const height = 500;
|
|
21
|
+
/// color: 0x1099bb,
|
|
22
|
+
return (
|
|
23
|
+
<div className="App">
|
|
24
|
+
<GsapPixieContextProvider>
|
|
25
|
+
<ChakraProvider>
|
|
26
|
+
<Flex flexDir={"column"}>
|
|
27
|
+
<Stage
|
|
28
|
+
width={width}
|
|
29
|
+
height={height}
|
|
30
|
+
// options={{ background: backgroundColor }}
|
|
31
|
+
options={{ backgroundColor: backgroundColorx, resolution: 2 }}
|
|
32
|
+
>
|
|
33
|
+
{children}
|
|
34
|
+
</Stage>
|
|
35
|
+
<Box mt={5} w={600}>
|
|
36
|
+
<VideoSeekBar />
|
|
37
|
+
</Box>
|
|
38
|
+
</Flex>
|
|
39
|
+
</ChakraProvider>
|
|
40
|
+
</GsapPixieContextProvider>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// your Stage:
|
|
2
|
+
// the context bridge:
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
const ContextBridge = <T,>({
|
|
6
|
+
children,
|
|
7
|
+
Context,
|
|
8
|
+
render,
|
|
9
|
+
}: {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
Context: React.Context<T>;
|
|
12
|
+
render: (children: React.ReactNode) => JSX.Element;
|
|
13
|
+
}) => {
|
|
14
|
+
return (
|
|
15
|
+
<Context.Consumer>
|
|
16
|
+
{(value) => {
|
|
17
|
+
return render(
|
|
18
|
+
<Context.Provider value={value}>{children}</Context.Provider>,
|
|
19
|
+
);
|
|
20
|
+
}}
|
|
21
|
+
</Context.Consumer>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default ContextBridge;
|
|
@@ -1,8 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
interface Ease {
|
|
2
|
+
from?: {
|
|
3
|
+
duration: number;
|
|
4
|
+
ease: string;
|
|
5
|
+
y?: number;
|
|
6
|
+
x?: number;
|
|
7
|
+
};
|
|
8
|
+
fromTo?: {
|
|
9
|
+
from: {
|
|
10
|
+
y?: number;
|
|
11
|
+
x?: number;
|
|
12
|
+
alpha?: number;
|
|
13
|
+
};
|
|
14
|
+
to: {
|
|
15
|
+
ease: string;
|
|
16
|
+
y?: number;
|
|
17
|
+
x?: number;
|
|
18
|
+
alpha?: number;
|
|
19
|
+
duration: number;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
to?: {
|
|
23
|
+
ease: string;
|
|
24
|
+
alpha: number;
|
|
25
|
+
duration: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
3
28
|
|
|
4
|
-
export const getAnimByName = (
|
|
5
|
-
|
|
29
|
+
export const getAnimByName = (
|
|
30
|
+
animate: string,
|
|
31
|
+
stageWidth?: number,
|
|
32
|
+
stageHeight?: number,
|
|
33
|
+
x?: number,
|
|
34
|
+
y?: number,
|
|
35
|
+
): Ease => {
|
|
36
|
+
let ease: Ease = {};
|
|
6
37
|
switch (animate) {
|
|
7
38
|
case "NONE":
|
|
8
39
|
case "none":
|