| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import React, { useEffect, useState } from 'react'; |
| import styled from 'styled-components'; |
| import { white } from '../styleVariables'; |
| import gremlintLoadingLogoColored from '../gremlint-loading-logo-colored.png'; |
| import gremlintLoadingLogoGrayscale from '../gremlint-loading-logo-grayscale.png'; |
| |
| const LoadingAnimationWrapper = styled.div` |
| position: fixed; |
| background: ${white}; |
| top: 0; |
| right: 0; |
| bottom: 0; |
| left: 0; |
| z-index: 2; |
| `; |
| |
| const GrayscaleImageWrapper = styled.div` |
| height: 100%; |
| width: 100%; |
| position: absolute; |
| bottom: calc(50vh - 25vmin); |
| `; |
| |
| const ColoredImageWrapper = styled.div<{ $loadingCompletion: number }>` |
| overflow: hidden; |
| height: ${({ $loadingCompletion }) => $loadingCompletion / 2}vmin; |
| width: 100%; |
| position: absolute; |
| bottom: calc(50vh - 25vmin); |
| `; |
| |
| const Image = styled.img<{ $opacity: number }>` |
| opacity: ${({ $opacity }) => $opacity}; |
| transition: 0.25s; |
| height: 50vmin; |
| width: 50vmin; |
| display: block; |
| margin: auto; |
| position: absolute; |
| bottom: 0; |
| left: 50%; |
| transform: translate(-50%, 0); |
| `; |
| |
| type LoadingAnimationProps = { |
| onLoadingComplete: VoidFunction; |
| }; |
| |
| const LoadingAnimation = ({ onLoadingComplete }: LoadingAnimationProps) => { |
| const [loadingCompletion, setLoadingCompletion] = useState(0); |
| const [coloredImageHasLoaded, setColoredImageHasLoaded] = useState(false); |
| const [grayscaleImageHasLoaded, setGrayscaleImageHasLoaded] = useState(false); |
| |
| useEffect(() => { |
| setTimeout( |
| () => { |
| if (loadingCompletion < 100) { |
| if (coloredImageHasLoaded && grayscaleImageHasLoaded) { |
| setLoadingCompletion(loadingCompletion + 1); |
| } |
| } else { |
| setTimeout(onLoadingComplete, 250); |
| } |
| }, |
| loadingCompletion === 0 ? 250 : 10, |
| ); |
| }, [loadingCompletion, coloredImageHasLoaded, grayscaleImageHasLoaded, onLoadingComplete]); |
| |
| return ( |
| <LoadingAnimationWrapper> |
| <GrayscaleImageWrapper> |
| <Image |
| src={gremlintLoadingLogoGrayscale} |
| $opacity={grayscaleImageHasLoaded && loadingCompletion !== 100 ? 1 : 0} |
| onLoad={() => setGrayscaleImageHasLoaded(true)} |
| /> |
| </GrayscaleImageWrapper> |
| <ColoredImageWrapper $loadingCompletion={loadingCompletion}> |
| <Image |
| src={gremlintLoadingLogoColored} |
| $opacity={loadingCompletion !== 100 ? 1 : 0} |
| onLoad={() => setColoredImageHasLoaded(true)} |
| /> |
| </ColoredImageWrapper> |
| </LoadingAnimationWrapper> |
| ); |
| }; |
| |
| export default LoadingAnimation; |