@remotion/paths 4.0.0-webhook.27 → 4.1.0-alpha2
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/LICENSE.md +1 -1
- package/README.md +1 -2
- package/dist/evolve-path.d.ts +2 -2
- package/dist/evolve-path.js +2 -2
- package/dist/extend-viewbox.d.ts +2 -2
- package/dist/extend-viewbox.js +2 -2
- package/dist/get-bounding-box.d.ts +8 -0
- package/dist/get-bounding-box.js +185 -0
- package/dist/get-length.d.ts +2 -2
- package/dist/get-length.js +2 -2
- package/dist/get-point-at-length.d.ts +2 -2
- package/dist/get-point-at-length.js +2 -2
- package/dist/get-subpaths.d.ts +6 -0
- package/dist/get-subpaths.js +19 -0
- package/dist/get-tangent-at-length.d.ts +2 -2
- package/dist/get-tangent-at-length.js +2 -2
- package/dist/helpers/arc.d.ts +0 -0
- package/dist/helpers/arc.js +0 -0
- package/dist/helpers/bezier-functions.d.ts +0 -0
- package/dist/helpers/bezier-functions.js +0 -0
- package/dist/helpers/bezier-values.d.ts +0 -0
- package/dist/helpers/bezier-values.js +0 -0
- package/dist/helpers/bezier.d.ts +0 -0
- package/dist/helpers/bezier.js +0 -0
- package/dist/helpers/construct.d.ts +9 -1
- package/dist/helpers/construct.js +218 -128
- package/dist/helpers/get-part-at-length.d.ts +0 -0
- package/dist/helpers/get-part-at-length.js +0 -0
- package/dist/helpers/iterate.d.ts +14 -0
- package/dist/helpers/iterate.js +95 -0
- package/dist/helpers/linear.d.ts +6 -1
- package/dist/helpers/linear.js +1 -1
- package/dist/helpers/remove-a-s-t-curves.d.ts +2 -0
- package/dist/helpers/remove-a-s-t-curves.js +271 -0
- package/dist/helpers/split-curve.d.ts +1 -1
- package/dist/helpers/split-curve.js +0 -0
- package/dist/helpers/types.d.ts +109 -2
- package/dist/helpers/types.js +0 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.js +19 -3
- package/dist/interpolate-path.d.ts +2 -2
- package/dist/interpolate-path.js +2 -2
- package/dist/normalize-path.d.ts +4 -2
- package/dist/normalize-path.js +141 -277
- package/dist/parse-path.d.ts +8 -0
- package/dist/parse-path.js +265 -0
- package/dist/reduce-instructions.d.ts +7 -0
- package/dist/reduce-instructions.js +15 -0
- package/dist/reset-path.d.ts +6 -0
- package/dist/reset-path.js +15 -0
- package/dist/reverse-path.d.ts +2 -2
- package/dist/reverse-path.js +73 -118
- package/dist/scale-path.d.ts +10 -0
- package/dist/scale-path.js +180 -0
- package/dist/serialize-instructions.d.ts +2 -0
- package/dist/serialize-instructions.js +78 -0
- package/dist/translate-path.d.ts +11 -0
- package/dist/translate-path.js +116 -0
- package/dist/warp-path/index.d.ts +10 -0
- package/dist/warp-path/index.js +26 -0
- package/dist/warp-path/warp-helpers.d.ts +14 -0
- package/dist/warp-path/warp-helpers.js +229 -0
- package/package.json +38 -38
- package/.prettierrc.js +0 -14
- package/dist/get-parts.d.ts +0 -7
- package/dist/get-parts.js +0 -31
- package/dist/helpers/parse.d.ts +0 -2
- package/dist/helpers/parse.js +0 -49
- package/tsconfig.json +0 -9
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scalePath = void 0;
|
|
4
|
+
const get_bounding_box_1 = require("./get-bounding-box");
|
|
5
|
+
const parse_path_1 = require("./parse-path");
|
|
6
|
+
const reduce_instructions_1 = require("./reduce-instructions");
|
|
7
|
+
const serialize_instructions_1 = require("./serialize-instructions");
|
|
8
|
+
const translate_path_1 = require("./translate-path");
|
|
9
|
+
/**
|
|
10
|
+
* @description Allows you to grow or shrink the size of a path.
|
|
11
|
+
* @param {string} path A valid SVG path
|
|
12
|
+
* @param {string} d
|
|
13
|
+
* @param {Number} scaleX
|
|
14
|
+
* @param {Number} scaleY
|
|
15
|
+
* @returns a new path with respect to the scale values provided
|
|
16
|
+
* @see [Documentation](https://www.remotion.dev/docs/paths/scale-path)
|
|
17
|
+
*/
|
|
18
|
+
const scalePath = (d, scaleX, scaleY) => {
|
|
19
|
+
const reduced = (0, reduce_instructions_1.reduceInstructions)((0, parse_path_1.parsePath)(d));
|
|
20
|
+
const bounded = (0, get_bounding_box_1.getBoundingBoxFromInstructions)(reduced);
|
|
21
|
+
const zeroed = (0, translate_path_1.translateSegments)(reduced, -bounded.x1, -bounded.y1);
|
|
22
|
+
const mapped = zeroed.map((instruction) => {
|
|
23
|
+
if (instruction.type === 'L') {
|
|
24
|
+
return {
|
|
25
|
+
type: 'L',
|
|
26
|
+
x: scaleX * instruction.x,
|
|
27
|
+
y: scaleY * instruction.y,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (instruction.type === 'C') {
|
|
31
|
+
return {
|
|
32
|
+
type: 'C',
|
|
33
|
+
x: scaleX * instruction.x,
|
|
34
|
+
y: scaleY * instruction.y,
|
|
35
|
+
cp1x: scaleX * instruction.cp1x,
|
|
36
|
+
cp1y: scaleY * instruction.cp1y,
|
|
37
|
+
cp2x: scaleX * instruction.cp2x,
|
|
38
|
+
cp2y: scaleY * instruction.cp2y,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (instruction.type === 'M') {
|
|
42
|
+
return {
|
|
43
|
+
type: 'M',
|
|
44
|
+
x: scaleX * instruction.x,
|
|
45
|
+
y: scaleY * instruction.y,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (instruction.type === 'Q') {
|
|
49
|
+
return {
|
|
50
|
+
type: 'Q',
|
|
51
|
+
x: scaleX * instruction.x,
|
|
52
|
+
y: scaleY * instruction.y,
|
|
53
|
+
cpx: scaleX * instruction.cpx,
|
|
54
|
+
cpy: scaleY * instruction.cpy,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (instruction.type === 'Z') {
|
|
58
|
+
return {
|
|
59
|
+
type: 'Z',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (instruction.type === 'A') {
|
|
63
|
+
return {
|
|
64
|
+
type: 'A',
|
|
65
|
+
largeArcFlag: instruction.largeArcFlag,
|
|
66
|
+
rx: scaleX * instruction.rx,
|
|
67
|
+
ry: scaleY * instruction.ry,
|
|
68
|
+
sweepFlag: instruction.sweepFlag,
|
|
69
|
+
xAxisRotation: instruction.xAxisRotation,
|
|
70
|
+
x: scaleX * instruction.x,
|
|
71
|
+
y: scaleY * instruction.y,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (instruction.type === 'H') {
|
|
75
|
+
return {
|
|
76
|
+
type: 'H',
|
|
77
|
+
x: scaleX * instruction.x,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (instruction.type === 'S') {
|
|
81
|
+
return {
|
|
82
|
+
type: 'S',
|
|
83
|
+
cpx: scaleX * instruction.cpx,
|
|
84
|
+
cpy: scaleY * instruction.cpy,
|
|
85
|
+
x: scaleX * instruction.x,
|
|
86
|
+
y: scaleY * instruction.y,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (instruction.type === 'T') {
|
|
90
|
+
return {
|
|
91
|
+
type: 'T',
|
|
92
|
+
x: scaleX * instruction.x,
|
|
93
|
+
y: scaleY * instruction.y,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (instruction.type === 'V') {
|
|
97
|
+
return {
|
|
98
|
+
type: 'V',
|
|
99
|
+
y: scaleY * instruction.y,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (instruction.type === 'a') {
|
|
103
|
+
return {
|
|
104
|
+
type: 'a',
|
|
105
|
+
dx: scaleX * instruction.dx,
|
|
106
|
+
dy: scaleY * instruction.dy,
|
|
107
|
+
largeArcFlag: instruction.largeArcFlag,
|
|
108
|
+
rx: scaleX * instruction.rx,
|
|
109
|
+
ry: scaleY * instruction.ry,
|
|
110
|
+
sweepFlag: instruction.sweepFlag,
|
|
111
|
+
xAxisRotation: instruction.xAxisRotation,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (instruction.type === 'c') {
|
|
115
|
+
return {
|
|
116
|
+
type: 'c',
|
|
117
|
+
cp1dx: scaleX * instruction.cp1dx,
|
|
118
|
+
cp1dy: scaleY * instruction.cp1dy,
|
|
119
|
+
cp2dx: scaleX * instruction.cp2dx,
|
|
120
|
+
cp2dy: scaleY * instruction.cp2dy,
|
|
121
|
+
dx: scaleX * instruction.dx,
|
|
122
|
+
dy: scaleY * instruction.dy,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (instruction.type === 'h') {
|
|
126
|
+
return {
|
|
127
|
+
type: 'h',
|
|
128
|
+
dx: scaleX * instruction.dx,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if (instruction.type === 'l') {
|
|
132
|
+
return {
|
|
133
|
+
type: 'l',
|
|
134
|
+
dx: scaleX * instruction.dx,
|
|
135
|
+
dy: scaleY * instruction.dy,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (instruction.type === 'm') {
|
|
139
|
+
return {
|
|
140
|
+
type: 'm',
|
|
141
|
+
dx: scaleX * instruction.dx,
|
|
142
|
+
dy: scaleY * instruction.dy,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (instruction.type === 'q') {
|
|
146
|
+
return {
|
|
147
|
+
type: 'q',
|
|
148
|
+
cpdx: scaleX * instruction.cpdx,
|
|
149
|
+
cpdy: scaleY * instruction.cpdy,
|
|
150
|
+
dx: scaleX * instruction.dx,
|
|
151
|
+
dy: scaleY * instruction.dy,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (instruction.type === 's') {
|
|
155
|
+
return {
|
|
156
|
+
type: 's',
|
|
157
|
+
cpdx: scaleX * instruction.cpdx,
|
|
158
|
+
cpdy: scaleY * instruction.cpdy,
|
|
159
|
+
dx: scaleX * instruction.dx,
|
|
160
|
+
dy: scaleY * instruction.dy,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if (instruction.type === 't') {
|
|
164
|
+
return {
|
|
165
|
+
type: 't',
|
|
166
|
+
dx: scaleX * instruction.dx,
|
|
167
|
+
dy: scaleY * instruction.dy,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if (instruction.type === 'v') {
|
|
171
|
+
return {
|
|
172
|
+
type: 'v',
|
|
173
|
+
dy: scaleY * instruction.dy,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
throw new Error('unexpected function');
|
|
177
|
+
});
|
|
178
|
+
return (0, serialize_instructions_1.serializeInstructions)((0, translate_path_1.translateSegments)(mapped, bounded.x1, bounded.y1));
|
|
179
|
+
};
|
|
180
|
+
exports.scalePath = scalePath;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serializeInstructions = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @description Takes an array of Instruction's and serializes it into an SVG path string.
|
|
6
|
+
* @param {Array} instruction
|
|
7
|
+
* @returns a serialized SVG path string
|
|
8
|
+
* @see [Documentation](https://www.remotion.dev/docs/paths/serialize-instructions)
|
|
9
|
+
*/
|
|
10
|
+
const serializeInstruction = (instruction) => {
|
|
11
|
+
if (instruction.type === 'A') {
|
|
12
|
+
return `A ${instruction.rx} ${instruction.ry} ${instruction.xAxisRotation} ${Number(instruction.largeArcFlag)} ${Number(instruction.sweepFlag)} ${instruction.x} ${instruction.y}`;
|
|
13
|
+
}
|
|
14
|
+
if (instruction.type === 'a') {
|
|
15
|
+
return `a ${instruction.rx} ${instruction.ry} ${instruction.xAxisRotation} ${Number(instruction.largeArcFlag)} ${Number(instruction.sweepFlag)} ${instruction.dx} ${instruction.dy}`;
|
|
16
|
+
}
|
|
17
|
+
if (instruction.type === 'C') {
|
|
18
|
+
return `C ${instruction.cp1x} ${instruction.cp1y} ${instruction.cp2x} ${instruction.cp2y} ${instruction.x} ${instruction.y}`;
|
|
19
|
+
}
|
|
20
|
+
if (instruction.type === 'c') {
|
|
21
|
+
return `c ${instruction.cp1dx} ${instruction.cp1dy} ${instruction.cp2dx} ${instruction.cp2dy} ${instruction.dx} ${instruction.dy}`;
|
|
22
|
+
}
|
|
23
|
+
if (instruction.type === 'S') {
|
|
24
|
+
return `S ${instruction.cpx} ${instruction.cpy} ${instruction.x} ${instruction.y}`;
|
|
25
|
+
}
|
|
26
|
+
if (instruction.type === 's') {
|
|
27
|
+
return `s ${instruction.cpdx} ${instruction.cpdy} ${instruction.dx} ${instruction.dy}`;
|
|
28
|
+
}
|
|
29
|
+
if (instruction.type === 'Q') {
|
|
30
|
+
return `Q ${instruction.cpx} ${instruction.cpy} ${instruction.x} ${instruction.y}`;
|
|
31
|
+
}
|
|
32
|
+
if (instruction.type === 'q') {
|
|
33
|
+
return `q ${instruction.cpdx} ${instruction.cpdy} ${instruction.dx} ${instruction.dy}`;
|
|
34
|
+
}
|
|
35
|
+
if (instruction.type === 'Z') {
|
|
36
|
+
return 'Z';
|
|
37
|
+
}
|
|
38
|
+
if (instruction.type === 'H') {
|
|
39
|
+
return `H ${instruction.x}`;
|
|
40
|
+
}
|
|
41
|
+
if (instruction.type === 'h') {
|
|
42
|
+
return `h ${instruction.dx}`;
|
|
43
|
+
}
|
|
44
|
+
if (instruction.type === 'V') {
|
|
45
|
+
return `V ${instruction.y}`;
|
|
46
|
+
}
|
|
47
|
+
if (instruction.type === 'v') {
|
|
48
|
+
return `v ${instruction.dy}`;
|
|
49
|
+
}
|
|
50
|
+
if (instruction.type === 'L') {
|
|
51
|
+
return `L ${instruction.x} ${instruction.y}`;
|
|
52
|
+
}
|
|
53
|
+
if (instruction.type === 'l') {
|
|
54
|
+
return `l ${instruction.dx} ${instruction.dy}`;
|
|
55
|
+
}
|
|
56
|
+
if (instruction.type === 'M') {
|
|
57
|
+
return `M ${instruction.x} ${instruction.y}`;
|
|
58
|
+
}
|
|
59
|
+
if (instruction.type === 'm') {
|
|
60
|
+
return `m ${instruction.dx} ${instruction.dy}`;
|
|
61
|
+
}
|
|
62
|
+
if (instruction.type === 'T') {
|
|
63
|
+
return `T ${instruction.x} ${instruction.y}`;
|
|
64
|
+
}
|
|
65
|
+
if (instruction.type === 't') {
|
|
66
|
+
return `t ${instruction.dx} ${instruction.dy}`;
|
|
67
|
+
}
|
|
68
|
+
// @ts-expect-error
|
|
69
|
+
throw new Error(`Unknown instruction type: ${instruction.type}`);
|
|
70
|
+
};
|
|
71
|
+
const serializeInstructions = (path) => {
|
|
72
|
+
return path
|
|
73
|
+
.map((p) => {
|
|
74
|
+
return serializeInstruction(p);
|
|
75
|
+
})
|
|
76
|
+
.join(' ');
|
|
77
|
+
};
|
|
78
|
+
exports.serializeInstructions = serializeInstructions;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Instruction } from './helpers/types';
|
|
2
|
+
export declare const translateSegments: (segments: Instruction[], x: number, y: number) => Instruction[];
|
|
3
|
+
/**
|
|
4
|
+
* @description Translates the path by the given x and y coordinates.
|
|
5
|
+
* @param {string} path the originalSVG path
|
|
6
|
+
* @param {Number} x the amount of horizontal translation
|
|
7
|
+
* @param {Number} y the amount of vertical translation
|
|
8
|
+
* @returns a new string containing a path, if it is valid
|
|
9
|
+
* @see [Documentation](https://www.remotion.dev/docs/paths/translate-path)
|
|
10
|
+
*/
|
|
11
|
+
export declare const translatePath: (path: string, x: number, y: number) => string;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.translatePath = exports.translateSegments = void 0;
|
|
4
|
+
const parse_path_1 = require("./parse-path");
|
|
5
|
+
const serialize_instructions_1 = require("./serialize-instructions");
|
|
6
|
+
const translateSegments = (segments, x, y) => {
|
|
7
|
+
return segments.map((segment) => {
|
|
8
|
+
// Shift coords only for commands with absolute values
|
|
9
|
+
if (segment.type === 'a' ||
|
|
10
|
+
segment.type === 'c' ||
|
|
11
|
+
segment.type === 'v' ||
|
|
12
|
+
segment.type === 's' ||
|
|
13
|
+
segment.type === 'h' ||
|
|
14
|
+
segment.type === 'l' ||
|
|
15
|
+
segment.type === 'm' ||
|
|
16
|
+
segment.type === 'q' ||
|
|
17
|
+
segment.type === 't') {
|
|
18
|
+
return segment;
|
|
19
|
+
}
|
|
20
|
+
// V is the only command, with shifted coords parity
|
|
21
|
+
if (segment.type === 'V') {
|
|
22
|
+
return {
|
|
23
|
+
type: 'V',
|
|
24
|
+
y: segment.y + y,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (segment.type === 'H') {
|
|
28
|
+
return {
|
|
29
|
+
type: 'H',
|
|
30
|
+
x: segment.x + x,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]
|
|
34
|
+
// touch x, y only
|
|
35
|
+
if (segment.type === 'A') {
|
|
36
|
+
return {
|
|
37
|
+
type: 'A',
|
|
38
|
+
rx: segment.rx,
|
|
39
|
+
ry: segment.ry,
|
|
40
|
+
largeArcFlag: segment.largeArcFlag,
|
|
41
|
+
sweepFlag: segment.sweepFlag,
|
|
42
|
+
xAxisRotation: segment.xAxisRotation,
|
|
43
|
+
x: segment.x + x,
|
|
44
|
+
y: segment.y + y,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (segment.type === 'Z') {
|
|
48
|
+
return segment;
|
|
49
|
+
}
|
|
50
|
+
if (segment.type === 'C') {
|
|
51
|
+
return {
|
|
52
|
+
type: 'C',
|
|
53
|
+
cp1x: segment.cp1x + x,
|
|
54
|
+
cp1y: segment.cp1y + y,
|
|
55
|
+
cp2x: segment.cp2x + x,
|
|
56
|
+
cp2y: segment.cp2y + y,
|
|
57
|
+
x: segment.x + x,
|
|
58
|
+
y: segment.y + y,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (segment.type === 'Q') {
|
|
62
|
+
return {
|
|
63
|
+
type: 'Q',
|
|
64
|
+
cpx: segment.cpx + x,
|
|
65
|
+
cpy: segment.cpy + y,
|
|
66
|
+
x: segment.x + x,
|
|
67
|
+
y: segment.y + y,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (segment.type === 'S') {
|
|
71
|
+
return {
|
|
72
|
+
type: 'S',
|
|
73
|
+
cpx: segment.cpx + x,
|
|
74
|
+
cpy: segment.cpy + y,
|
|
75
|
+
x: segment.x + x,
|
|
76
|
+
y: segment.y + y,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (segment.type === 'T') {
|
|
80
|
+
return {
|
|
81
|
+
type: 'T',
|
|
82
|
+
x: segment.x + x,
|
|
83
|
+
y: segment.y + y,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (segment.type === 'L') {
|
|
87
|
+
return {
|
|
88
|
+
type: 'L',
|
|
89
|
+
x: segment.x + x,
|
|
90
|
+
y: segment.y + y,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (segment.type === 'M') {
|
|
94
|
+
return {
|
|
95
|
+
type: 'M',
|
|
96
|
+
x: segment.x + x,
|
|
97
|
+
y: segment.y + y,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// @ts-expect-error
|
|
101
|
+
throw new Error(`Unknown segment type: ${segment.type}`);
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
exports.translateSegments = translateSegments;
|
|
105
|
+
/**
|
|
106
|
+
* @description Translates the path by the given x and y coordinates.
|
|
107
|
+
* @param {string} path the originalSVG path
|
|
108
|
+
* @param {Number} x the amount of horizontal translation
|
|
109
|
+
* @param {Number} y the amount of vertical translation
|
|
110
|
+
* @returns a new string containing a path, if it is valid
|
|
111
|
+
* @see [Documentation](https://www.remotion.dev/docs/paths/translate-path)
|
|
112
|
+
*/
|
|
113
|
+
const translatePath = (path, x, y) => {
|
|
114
|
+
return (0, serialize_instructions_1.serializeInstructions)((0, exports.translateSegments)((0, parse_path_1.parsePath)(path), x, y));
|
|
115
|
+
};
|
|
116
|
+
exports.translatePath = translatePath;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WarpPathFn } from './warp-helpers';
|
|
2
|
+
/**
|
|
3
|
+
* @description This function works by splitting SVG instructions into many smaller SVG instructions and then remapping the coordinates of each instruction.
|
|
4
|
+
* @param {string} path an SVG path string
|
|
5
|
+
* @see [Documentation](https://www.remotion.dev/docs/paths/warp-path)
|
|
6
|
+
*/
|
|
7
|
+
export declare const warpPath: (path: string, transformer: WarpPathFn, options?: {
|
|
8
|
+
interpolationThreshold?: number;
|
|
9
|
+
}) => string;
|
|
10
|
+
export type { WarpPathFn } from './warp-helpers';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.warpPath = void 0;
|
|
4
|
+
const get_bounding_box_1 = require("../get-bounding-box");
|
|
5
|
+
const parse_path_1 = require("../parse-path");
|
|
6
|
+
const reduce_instructions_1 = require("../reduce-instructions");
|
|
7
|
+
const serialize_instructions_1 = require("../serialize-instructions");
|
|
8
|
+
const warp_helpers_1 = require("./warp-helpers");
|
|
9
|
+
const getDefaultInterpolationThreshold = (instructions) => {
|
|
10
|
+
const boundingBox = (0, get_bounding_box_1.getBoundingBoxFromInstructions)(instructions);
|
|
11
|
+
const longer = Math.max(boundingBox.y2 - boundingBox.y1, boundingBox.x2 - boundingBox.x1);
|
|
12
|
+
return longer * 0.01;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* @description This function works by splitting SVG instructions into many smaller SVG instructions and then remapping the coordinates of each instruction.
|
|
16
|
+
* @param {string} path an SVG path string
|
|
17
|
+
* @see [Documentation](https://www.remotion.dev/docs/paths/warp-path)
|
|
18
|
+
*/
|
|
19
|
+
const warpPath = (path, transformer, options) => {
|
|
20
|
+
var _a;
|
|
21
|
+
const reduced = (0, reduce_instructions_1.reduceInstructions)((0, parse_path_1.parsePath)(path));
|
|
22
|
+
const withZFix = (0, warp_helpers_1.fixZInstruction)(reduced);
|
|
23
|
+
const interpolated = (0, warp_helpers_1.svgPathInterpolate)(withZFix, (_a = options === null || options === void 0 ? void 0 : options.interpolationThreshold) !== null && _a !== void 0 ? _a : getDefaultInterpolationThreshold(withZFix));
|
|
24
|
+
return (0, serialize_instructions_1.serializeInstructions)((0, warp_helpers_1.warpTransform)(interpolated, transformer));
|
|
25
|
+
};
|
|
26
|
+
exports.warpPath = warpPath;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReducedInstruction } from '../helpers/types';
|
|
2
|
+
export type WarpPathFn = (point: {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
}) => {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function svgPathInterpolate(path: ReducedInstruction[], threshold: number): ReducedInstruction[];
|
|
10
|
+
export declare const warpTransform: (path: ReducedInstruction[], transformer: WarpPathFn) => ReducedInstruction[];
|
|
11
|
+
export declare const fixZInstruction: (instructions: ReducedInstruction[]) => ReducedInstruction[];
|
|
12
|
+
export declare function interpolateUntil(points: [number, number][], threshold: number, deltaFunction?: (points: [number, number][]) => number): [number, number][][];
|
|
13
|
+
export declare function split(p: number[][], t?: number): number[][][];
|
|
14
|
+
export declare function createLineSegment(points: number[][]): ReducedInstruction;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createLineSegment = exports.split = exports.interpolateUntil = exports.fixZInstruction = exports.warpTransform = exports.svgPathInterpolate = void 0;
|
|
4
|
+
function svgPathInterpolate(path, threshold) {
|
|
5
|
+
let didWork = false;
|
|
6
|
+
const deltaFunction = (points) => {
|
|
7
|
+
const linearPoints = [
|
|
8
|
+
points[0].slice(0, 2),
|
|
9
|
+
points[points.length - 1].slice(0, 2),
|
|
10
|
+
];
|
|
11
|
+
const delta = euclideanDistance(linearPoints);
|
|
12
|
+
didWork = didWork || delta > threshold;
|
|
13
|
+
return delta;
|
|
14
|
+
};
|
|
15
|
+
return warpInterpolate(path, threshold, deltaFunction);
|
|
16
|
+
}
|
|
17
|
+
exports.svgPathInterpolate = svgPathInterpolate;
|
|
18
|
+
function warpInterpolate(path, threshold, deltaFunction) {
|
|
19
|
+
let prexX = 0;
|
|
20
|
+
let prexY = 0;
|
|
21
|
+
return path
|
|
22
|
+
.map((segment) => {
|
|
23
|
+
const points = [[prexX, prexY]];
|
|
24
|
+
if (segment.type !== 'Z') {
|
|
25
|
+
prexX = segment.x;
|
|
26
|
+
prexY = segment.y;
|
|
27
|
+
}
|
|
28
|
+
if (segment.type === 'C') {
|
|
29
|
+
points.push([segment.cp1x, segment.cp1y]);
|
|
30
|
+
points.push([segment.cp2x, segment.cp2y]);
|
|
31
|
+
points.push([segment.x, segment.y]);
|
|
32
|
+
}
|
|
33
|
+
if (segment.type === 'L') {
|
|
34
|
+
points.push([segment.x, segment.y]);
|
|
35
|
+
}
|
|
36
|
+
if (segment.type === 'Q') {
|
|
37
|
+
points.push([segment.cpx, segment.cpy]);
|
|
38
|
+
points.push([segment.x, segment.y]);
|
|
39
|
+
}
|
|
40
|
+
if (segment.type === 'C' ||
|
|
41
|
+
segment.type === 'Q' ||
|
|
42
|
+
segment.type === 'L') {
|
|
43
|
+
return interpolateUntil(points, threshold, deltaFunction).map((rawSegment) => createLineSegment(rawSegment));
|
|
44
|
+
}
|
|
45
|
+
return [segment];
|
|
46
|
+
})
|
|
47
|
+
.flat(1);
|
|
48
|
+
}
|
|
49
|
+
const warpTransform = (path, transformer) => {
|
|
50
|
+
return path
|
|
51
|
+
.map((segment) => {
|
|
52
|
+
if (segment.type === 'L') {
|
|
53
|
+
const { x, y } = transformer({ x: segment.x, y: segment.y });
|
|
54
|
+
return [
|
|
55
|
+
{
|
|
56
|
+
type: 'L',
|
|
57
|
+
x,
|
|
58
|
+
y,
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
if (segment.type === 'Q') {
|
|
63
|
+
const { x, y } = transformer({ x: segment.x, y: segment.y });
|
|
64
|
+
const { x: cpx, y: cpy } = transformer({
|
|
65
|
+
x: segment.cpx,
|
|
66
|
+
y: segment.cpy,
|
|
67
|
+
});
|
|
68
|
+
return [
|
|
69
|
+
{
|
|
70
|
+
type: 'Q',
|
|
71
|
+
x,
|
|
72
|
+
y,
|
|
73
|
+
cpx,
|
|
74
|
+
cpy,
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
if (segment.type === 'C') {
|
|
79
|
+
const { x, y } = transformer({ x: segment.x, y: segment.y });
|
|
80
|
+
const { x: cp1x, y: cp1y } = transformer({
|
|
81
|
+
x: segment.cp1x,
|
|
82
|
+
y: segment.cp1y,
|
|
83
|
+
});
|
|
84
|
+
const { x: cp2x, y: cp2y } = transformer({
|
|
85
|
+
x: segment.cp2x,
|
|
86
|
+
y: segment.cp2y,
|
|
87
|
+
});
|
|
88
|
+
return [
|
|
89
|
+
{
|
|
90
|
+
type: 'C',
|
|
91
|
+
x,
|
|
92
|
+
y,
|
|
93
|
+
cp1x,
|
|
94
|
+
cp1y,
|
|
95
|
+
cp2x,
|
|
96
|
+
cp2y,
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
if (segment.type === 'M') {
|
|
101
|
+
const { x, y } = transformer({ x: segment.x, y: segment.y });
|
|
102
|
+
return [
|
|
103
|
+
{
|
|
104
|
+
type: 'M',
|
|
105
|
+
x,
|
|
106
|
+
y,
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
return [segment];
|
|
111
|
+
})
|
|
112
|
+
.flat(1);
|
|
113
|
+
};
|
|
114
|
+
exports.warpTransform = warpTransform;
|
|
115
|
+
// Add a line from second to last point to last point and then keep Z so it can be transformed as well
|
|
116
|
+
const fixZInstruction = (instructions) => {
|
|
117
|
+
let prevX = 0;
|
|
118
|
+
let prevY = 0;
|
|
119
|
+
return instructions
|
|
120
|
+
.map((instruction) => {
|
|
121
|
+
if (instruction.type === 'Z') {
|
|
122
|
+
return [
|
|
123
|
+
{
|
|
124
|
+
type: 'L',
|
|
125
|
+
x: prevX,
|
|
126
|
+
y: prevY,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'Z',
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
if (instruction.type === 'M') {
|
|
134
|
+
prevX = instruction.x;
|
|
135
|
+
prevY = instruction.y;
|
|
136
|
+
}
|
|
137
|
+
return [instruction];
|
|
138
|
+
})
|
|
139
|
+
.flat(1);
|
|
140
|
+
};
|
|
141
|
+
exports.fixZInstruction = fixZInstruction;
|
|
142
|
+
const euclideanDistance = (points) => {
|
|
143
|
+
const startPoint = points[0];
|
|
144
|
+
const endPoint = points[points.length - 1];
|
|
145
|
+
let d2 = 0;
|
|
146
|
+
for (let i = 0; i < startPoint.length; i++) {
|
|
147
|
+
const d = endPoint[i] - startPoint[i];
|
|
148
|
+
d2 += d ** 2;
|
|
149
|
+
}
|
|
150
|
+
return Math.sqrt(d2);
|
|
151
|
+
};
|
|
152
|
+
function interpolateUntil(points, threshold, deltaFunction = euclideanDistance) {
|
|
153
|
+
const stack = [points];
|
|
154
|
+
const segments = [];
|
|
155
|
+
while (stack.length > 0) {
|
|
156
|
+
const currentPoints = stack.pop();
|
|
157
|
+
if (deltaFunction(currentPoints) > threshold) {
|
|
158
|
+
const newPoints = split(currentPoints);
|
|
159
|
+
// Add new segments backwards so they end up in correct order
|
|
160
|
+
for (let i = newPoints.length - 1; i >= 0; i--) {
|
|
161
|
+
stack.push(newPoints[i]);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
segments.push(currentPoints);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return segments;
|
|
169
|
+
}
|
|
170
|
+
exports.interpolateUntil = interpolateUntil;
|
|
171
|
+
function split(p, t = 0.5) {
|
|
172
|
+
const seg0 = [];
|
|
173
|
+
const seg1 = [];
|
|
174
|
+
const orders = [p];
|
|
175
|
+
while (orders.length < p.length) {
|
|
176
|
+
const q = orders[orders.length - 1];
|
|
177
|
+
const r = [];
|
|
178
|
+
for (let i = 1; i < q.length; i++) {
|
|
179
|
+
const q0 = q[i - 1];
|
|
180
|
+
const q1 = q[i];
|
|
181
|
+
const s = [];
|
|
182
|
+
const dim = Math.max(q0.length, q1.length);
|
|
183
|
+
for (let j = 0; j < dim; j++) {
|
|
184
|
+
const s0 = q0[j] || 0;
|
|
185
|
+
const s1 = q1[j] || 0;
|
|
186
|
+
s.push(s0 + (s1 - s0) * t);
|
|
187
|
+
}
|
|
188
|
+
r.push(s);
|
|
189
|
+
}
|
|
190
|
+
orders.push(r);
|
|
191
|
+
}
|
|
192
|
+
for (let i = 0; i < orders.length; i++) {
|
|
193
|
+
seg0.push(orders[i][0]);
|
|
194
|
+
seg1.push(orders[orders.length - 1 - i][i]);
|
|
195
|
+
}
|
|
196
|
+
return [seg0, seg1];
|
|
197
|
+
}
|
|
198
|
+
exports.split = split;
|
|
199
|
+
function createLineSegment(points) {
|
|
200
|
+
switch (points.length) {
|
|
201
|
+
case 2:
|
|
202
|
+
return {
|
|
203
|
+
type: 'L',
|
|
204
|
+
x: points[1][0],
|
|
205
|
+
y: points[1][1],
|
|
206
|
+
};
|
|
207
|
+
case 3:
|
|
208
|
+
return {
|
|
209
|
+
type: 'Q',
|
|
210
|
+
cpx: points[1][0],
|
|
211
|
+
cpy: points[1][1],
|
|
212
|
+
x: points[2][0],
|
|
213
|
+
y: points[2][1],
|
|
214
|
+
};
|
|
215
|
+
case 4:
|
|
216
|
+
return {
|
|
217
|
+
type: 'C',
|
|
218
|
+
cp1x: points[1][0],
|
|
219
|
+
cp1y: points[1][1],
|
|
220
|
+
cp2x: points[2][0],
|
|
221
|
+
cp2y: points[2][1],
|
|
222
|
+
x: points[3][0],
|
|
223
|
+
y: points[3][1],
|
|
224
|
+
};
|
|
225
|
+
default:
|
|
226
|
+
throw new Error('Expected 2, 3 or 4 points for a line segment, got ' + points.length);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
exports.createLineSegment = createLineSegment;
|