add loading and error handling for images
This commit is contained in:
parent
fc893a2584
commit
6d645c3dc0
13
src/App.css
13
src/App.css
|
@ -83,7 +83,7 @@ img {
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
float: left;
|
margin: 0;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
aspect-ratio: 2/3;
|
aspect-ratio: 2/3;
|
||||||
|
@ -109,6 +109,9 @@ img {
|
||||||
grid-area: 1/1;
|
grid-area: 1/1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.highlighted {
|
||||||
|
border: 0.1em solid gold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.overlay {
|
.overlay {
|
||||||
|
@ -121,10 +124,10 @@ img {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.highlighted>.overlay {
|
||||||
|
background-color: rgba(255, 222, 123, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
.overlay:hover {
|
.overlay:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlighted {
|
|
||||||
border: 0.1em solid gold;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import './defaults.css'
|
import './defaults.css'
|
||||||
import './App.css'
|
import './App.css'
|
||||||
|
import './spinner.css'
|
||||||
import { MovieWall } from './objects/movie-wall'
|
import { MovieWall } from './objects/movie-wall'
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import tmdb from './objects/tmdb'
|
import tmdb from './objects/tmdb'
|
||||||
|
|
|
@ -75,16 +75,24 @@ function Poster({ movie, config, listSimilar, setMovies, setChosenMovie, setSimi
|
||||||
setChosenMovie(movie)
|
setChosenMovie(movie)
|
||||||
listSimilar(config, movie, setMovies, setSimilarMoviesAvailable)
|
listSimilar(config, movie, setMovies, setSimilarMoviesAvailable)
|
||||||
}
|
}
|
||||||
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
|
const [hasError, setHasError] = useState(false)
|
||||||
const classes = [
|
const classes = [
|
||||||
"poster",
|
"poster",
|
||||||
isHighlighted ? "highlighted" : ""
|
isHighlighted ? "highlighted" : ""
|
||||||
].join(" ")
|
].join(" ")
|
||||||
return <div className={classes} >
|
return <div className={classes} >
|
||||||
<div className="overlay" onClick={() => clickHandler()}>
|
{isLoading ?
|
||||||
</div>
|
<div className="spinner-container">
|
||||||
|
<div className="lds-spinner"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div></div>
|
||||||
|
: <div className="overlay" onClick={() => clickHandler()}>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{hasError ?? <div className="spinner-container">⚠️</div>}
|
||||||
<img
|
<img
|
||||||
src={tmdb.makeImgUrl(movie.poster_path ?? "")}
|
src={tmdb.makeImgUrl(movie.poster_path ?? "")}
|
||||||
onLoad={() => console.log("LOADED IMG")}
|
onLoad={() => setIsLoading(false)}
|
||||||
|
onError={() => setHasError(true)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
.spinner-container {
|
||||||
|
margin: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner,
|
||||||
|
.lds-spinner div,
|
||||||
|
.lds-spinner div:after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner {
|
||||||
|
color: currentColor;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div {
|
||||||
|
transform-origin: 40px 40px;
|
||||||
|
animation: lds-spinner 1.2s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:after {
|
||||||
|
content: " ";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 3.2px;
|
||||||
|
left: 36.8px;
|
||||||
|
width: 6.4px;
|
||||||
|
height: 17.6px;
|
||||||
|
border-radius: 20%;
|
||||||
|
background: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(1) {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
animation-delay: -1.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(2) {
|
||||||
|
transform: rotate(30deg);
|
||||||
|
animation-delay: -1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(3) {
|
||||||
|
transform: rotate(60deg);
|
||||||
|
animation-delay: -0.9s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(4) {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
animation-delay: -0.8s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(5) {
|
||||||
|
transform: rotate(120deg);
|
||||||
|
animation-delay: -0.7s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(6) {
|
||||||
|
transform: rotate(150deg);
|
||||||
|
animation-delay: -0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(7) {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
animation-delay: -0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(8) {
|
||||||
|
transform: rotate(210deg);
|
||||||
|
animation-delay: -0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(9) {
|
||||||
|
transform: rotate(240deg);
|
||||||
|
animation-delay: -0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(10) {
|
||||||
|
transform: rotate(270deg);
|
||||||
|
animation-delay: -0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(11) {
|
||||||
|
transform: rotate(300deg);
|
||||||
|
animation-delay: -0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-spinner div:nth-child(12) {
|
||||||
|
transform: rotate(330deg);
|
||||||
|
animation-delay: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes lds-spinner {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue