-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
134 lines (116 loc) · 4.28 KB
/
index.ts
1
2
3
4
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import { attachInterceptor, detachInterceptor } from "./src/interceptor";
import { LottieAnimation } from "./src/lottie-objects/animation";
import { LottieLayer } from "./src/lottie-objects/layer";
import { LottieShape } from "./src/lottie-objects/shape";
import { LottieShapeBackground } from "./src/lottie-objects/shapes/background";
import { LottieShapeEllipse } from "./src/lottie-objects/shapes/ellipse";
import { LottieShapeRect } from "./src/lottie-objects/shapes/rect";
async function _saveLottie(
this: any,
duration: number,
callback: (result: any) => void,
options = {
delay: 0,
units: "seconds",
}
) {
console.log("this", this);
// validate parameters
if (!callback) {
throw TypeError("callback parameter must be provided");
}
if (typeof duration !== "number") {
throw TypeError("Duration parameter must be a number");
}
// extract variables for more comfortable use
const delay = (options && options.delay) || 0; // in seconds
const units = (options && options.units) || "seconds"; // either 'seconds' or 'frames'
// if arguments in the options object are not correct, cancel operation
if (typeof delay !== "number") {
throw TypeError("Delay parameter must be a number");
}
// if units is not seconds nor frames, throw error
if (units !== "seconds" && units !== "frames") {
throw TypeError('Units parameter must be either "frames" or "seconds"');
}
this._recording = true;
// get the project's framerate
let _frameRate = this._targetFrameRate;
// if it is undefined or some non useful value, assume it's 60
if (_frameRate === Infinity || _frameRate === undefined || _frameRate === 0) {
_frameRate = 60;
}
// check the mode we are in and how many frames
// that duration translates to
const nFrames = units === "seconds" ? duration * _frameRate : duration;
const nFramesDelay = units === "seconds" ? delay * _frameRate : delay;
const totalNumberOfFrames = nFrames + nFramesDelay;
// initialize variables for the frames processing
let frameIterator = nFramesDelay;
if (this._isGlobal) {
(window as any).frameCount = frameIterator;
} else {
this.frameCount = frameIterator;
}
// We first take every frame that we are going to use for the animation
// let frames = [];
// stop the loop since we are going to manually redraw
this.noLoop();
// Defer execution until the rest of the call stack finishes, allowing the
// rest of `setup` to be called (and, importantly, canvases hidden in setup
// to be unhidden.)
//
// Waiting on this empty promise means we'll continue as soon as setup
// finishes without waiting for another frame.
await Promise.resolve();
// attach interceptor
attachInterceptor(this);
while (frameIterator < totalNumberOfFrames) {
/*
we draw the next frame. this is important, since
busy sketches or low end devices might take longer
to render some frames. So we just wait for the frame
to be drawn and immediately save it to a buffer and continue
*/
this.redraw();
// TODO: capture everything in this redraw cycle
// depending on the context we'll extract the pixels one way
// or another
// let data = this.drawingContext.getImageData(
// 0,
// 0,
// this.width,
// this.height
// ).data;
// frames.push(data);
frameIterator++;
await new Promise((resolve) => setTimeout(resolve, 0));
}
const recordedData = detachInterceptor(this);
console.log(recordedData);
const animation = new LottieAnimation({ frameRate: 60, totalFrame: nFrames });
const lottieClassTypeMap: Record<string, typeof LottieShape> = {
ellipse: LottieShapeEllipse,
rect: LottieShapeRect,
background: LottieShapeBackground,
};
// TODO: wait 2 secs then use the sample object from
for (const [key, value] of Object.entries(recordedData)) {
console.log(value);
const ShapeClass = lottieClassTypeMap[value.type];
const layer = new LottieLayer({});
animation.addLayer(layer);
const shape = new ShapeClass({
name: key,
args: value.frames,
});
layer.addShape(shape);
}
console.log(animation.toJson());
callback(animation.toJson());
this._recording = false;
this.loop();
}
if ((window as any).p5) {
(window as any).p5.prototype.saveLottie = _saveLottie;
}