fade in for movie layers, too

gosh I hope I didn't break everything 😅
This commit is contained in:
Emi Matchu 2020-10-10 03:46:23 -07:00
parent 82f849f047
commit afe9fcf392
2 changed files with 29 additions and 16 deletions

View file

@ -2,7 +2,13 @@ import React from "react";
import { loadImage, safeImageUrl } from "../util";
function OutfitMovieLayer({ libraryUrl, width, height, isPaused = false }) {
function OutfitMovieLayer({
libraryUrl,
width,
height,
isPaused = false,
onLoad = null,
}) {
const [stage, setStage] = React.useState(null);
const [library, setLibrary] = React.useState(null);
const [movieClip, setMovieClip] = React.useState(null);
@ -74,6 +80,11 @@ function OutfitMovieLayer({ libraryUrl, width, height, isPaused = false }) {
// then another effect will perform subsequent updates.
stage.update();
// This is when we trigger `onLoad`: once we're actually showing it!
if (onLoad) {
onLoad();
}
return () => stage.removeChild(movieClip);
}, [stage, movieClip]);
@ -221,7 +232,7 @@ export async function loadMovieLibrary(librarySrc) {
const manifestImages = new Map(
library.properties.manifest.map(({ id, src }) => [
id,
loadImage({src: safeImageUrl(librarySrcDir + "/" + src)}),
loadImage({ src: safeImageUrl(librarySrcDir + "/" + src) }),
])
);
await Promise.all(manifestImages.values());

View file

@ -1,7 +1,7 @@
import React from "react";
import { Box, DarkMode, Flex, Text } from "@chakra-ui/core";
import { WarningIcon } from "@chakra-ui/icons";
import { css, cx } from "emotion";
import { css } from "emotion";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import OutfitMovieLayer, {
@ -179,7 +179,7 @@ export function OutfitLayers({
`}
timeout={200}
>
<FullScreenCenter zIndex={layer.zone.depth}>
<FadeInOnLoad as={FullScreenCenter} zIndex={layer.zone.depth}>
{layer.canvasMovieLibraryUrl ? (
<OutfitMovieLayer
libraryUrl={layer.canvasMovieLibraryUrl}
@ -188,7 +188,8 @@ export function OutfitLayers({
isPaused={isPaused}
/>
) : (
<FadeInImage
<Box
as="img"
src={getBestImageUrlForLayer(layer).src}
// The crossOrigin prop isn't strictly necessary for loading
// here (<img> tags are always allowed through CORS), but
@ -202,7 +203,7 @@ export function OutfitLayers({
maxHeight="100%"
/>
)}
</FullScreenCenter>
</FadeInOnLoad>
</CSSTransition>
))}
</TransitionGroup>
@ -351,20 +352,21 @@ export function usePreloadLayers(layers) {
}
/**
* FadeInImage is like a <Box as="img" />, but with one extra feature: once the
* image loads, we fade in!
* FadeInOnLoad attaches an `onLoad` handler to its single child, and fades in
* the container element once it triggers.
*/
function FadeInImage(props) {
function FadeInOnLoad({ children, ...props }) {
const [isLoaded, setIsLoaded] = React.useState(false);
const onLoad = React.useCallback(() => setIsLoaded(true), []);
const child = React.Children.only(children);
const wrappedChild = React.cloneElement(child, { onLoad });
return (
<Box
{...props}
as="img"
opacity={isLoaded ? 1 : 0}
transition="opacity 0.2s"
onLoad={() => setIsLoaded(true)}
/>
<Box opacity={isLoaded ? 1 : 0} transition="opacity 0.2s" {...props}>
{wrappedChild}
</Box>
);
}