2133
});
2134
// $FlowFixMe[prop-missing]
2135
ownerDocument.__reactViewTransition = transition;
2136
+
2137
+ const readyCallback = () => {
2138
+ const documentElement: Element = (ownerDocument.documentElement: any);
2139
+ // Loop through all View Transition Animations.
2140
+ const animations = documentElement.getAnimations({subtree: true});
2141
+ for (let i = 0; i < animations.length; i++) {
2142
+ const animation = animations[i];
2143
+ const effect: KeyframeEffect = (animation.effect: any);
2144
+ // $FlowFixMe
2145
+ const pseudoElement: ?string = effect.pseudoElement;
2146
+ if (
2147
+ pseudoElement != null &&
2148
+ pseudoElement.startsWith('::view-transition')
2149
+ ) {
2150
+ const keyframes = effect.getKeyframes();
2151
+ // Next, we're going to try to optimize this animation in case the auto-generated
2152
+ // width/height keyframes are unnecessary.
2153
+ let width;
2154
+ let height;
2155
+ let unchangedDimensions = true;
2156
+ for (let j = 0; j < keyframes.length; j++) {
2157
+ const keyframe = keyframes[j];
2158
+ const w = keyframe.width;
2159
+ if (width === undefined) {
2160
+ width = w;
2161
+ } else if (width !== w) {
2162
+ unchangedDimensions = false;
2163
+ break;
2164
+ }
2165
+ const h = keyframe.height;
2166
+ if (height === undefined) {
2167
+ height = h;
2168
+ } else if (height !== h) {
2169
+ unchangedDimensions = false;
2170
+ break;
2171
+ }
2172
+ // We're clearing the keyframes in case we are going to apply the optimization.
2173
+ delete keyframe.width;
2174
+ delete keyframe.height;
2175
+ if (keyframe.transform === 'none') {
2176
+ delete keyframe.transform;
2177
+ }
2178
+ }
2179
+ if (
2180
+ unchangedDimensions &&
2181
+ width !== undefined &&
2182
+ height !== undefined
2183
+ ) {
2184
+ // Replace the keyframes with ones that don't animate the width/height.
2185
+ // $FlowFixMe
2186
+ effect.setKeyframes(keyframes);
2187
+ // Read back the new animation to see what the underlying width/height of the pseudo-element was.
2188
+ const computedStyle = getComputedStyle(
2189
+ // $FlowFixMe
2190
+ effect.target,
2191
+ // $FlowFixMe
2192
+ effect.pseudoElement,
2193
+ );
2194
+ if (
2195
+ computedStyle.width !== width ||
2196
+ computedStyle.height !== height
2197
+ ) {
2198
+ // Oops. Turns out that the pseudo-element had a different width/height so we need to let it
2199
+ // be overridden. Add it back.
2200
+ const first = keyframes[0];
2201
+ first.width = width;
2202
+ first.height = height;
2203
+ const last = keyframes[keyframes.length - 1];
2204
+ last.width = width;
2205
+ last.height = height;
2206
+ // $FlowFixMe
2207
+ effect.setKeyframes(keyframes);
2208
+ }
2209
+ }
2210
+ }
2211
+ }
2212
+ spawnedWorkCallback();
2213
+ };
2214
const handleError = (error: mixed) => {
2215
try {
2216
error = customizeViewTransitionError(error, false);
2228
spawnedWorkCallback();
2229
}
2230
};
2153
- transition.ready.then(spawnedWorkCallback, handleError);
2231
+ transition.ready.then(readyCallback, handleError);
2232
transition.finished.finally(() => {
2233
cancelAllViewTransitionAnimations((ownerDocument.documentElement: any));
2234
// $FlowFixMe[prop-missing]
2298
moveFirstFrameIntoViewport: boolean,
2299
moveAllFramesIntoViewport: boolean,
2300
) {
2301
+ let width;
2302
+ let height;
2303
+ let unchangedDimensions = true;
2304
for (let i = 0; i < keyframes.length; i++) {
2305
const keyframe = keyframes[i];
2306
// Delete any easing since we always apply linear easing to gestures.
2307
delete keyframe.easing;
2308
delete keyframe.computedOffset;
2309
+ const w = keyframe.width;
2310
+ if (width === undefined) {
2311
+ width = w;
2312
+ } else if (width !== w) {
2313
+ unchangedDimensions = false;
2314
+ }
2315
+ const h = keyframe.height;
2316
+ if (height === undefined) {
2317
+ height = h;
2318
+ } else if (height !== h) {
2319
+ unchangedDimensions = false;
2320
+ }
2321
// Chrome returns "auto" for width/height which is not a valid value to
2322
// animate to. Similarly, transform: "none" is actually lack of transform.
2323
if (keyframe.width === 'auto') {
2366
// keyframe. Otherwise it applies to every keyframe.
2367
moveOldFrameIntoViewport(keyframes[0]);
2368
}
2369
+ if (unchangedDimensions && width !== undefined && height !== undefined) {
2370
+ // Read the underlying width/height of the pseudo-element. The previous animation
2371
+ // should have already been cancelled so we should observe the underlying element.
2372
+ const computedStyle = getComputedStyle(targetElement, pseudoElement);
2373
+ if (computedStyle.width === width && computedStyle.height === height) {
2374
+ for (let i = 0; i < keyframes.length; i++) {
2375
+ const keyframe = keyframes[i];
2376
+ delete keyframe.width;
2377
+ delete keyframe.height;
2378
+ }
2379
+ }
2380
+ }
2381
+
2382
// TODO: Reverse the reverse if the original direction is reverse.
2383
const reverse = rangeStart > rangeEnd;
2384
if (timeline instanceof AnimationTimeline) {