Skip to content

Commit

Permalink
viewtransition add
Browse files Browse the repository at this point in the history
  • Loading branch information
ErickSalazar44 committed Sep 18, 2023
1 parent 4f01ec8 commit d65b9a6
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 70 deletions.
42 changes: 29 additions & 13 deletions src/components/Home/MovieBackground.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { CiPlay1 } from "react-icons/ci";
import { viewNavigate } from "../../utils/animationNavigate";
import { flushSync } from "react-dom";

const MovieBackground = ({
movies,
genreNamesByIds,
currentIndex,
navigate
navigate,
}) => {
const [backgroundImage, setBackgroundImage] = useState(
`https://image.tmdb.org/t/p/w780${movies?.[currentIndex]?.poster_path}`
);

const title = useRef(null);
useEffect(() => {
if (movies) {
const handleResize = () => {
Expand All @@ -25,10 +26,10 @@ const MovieBackground = ({
);
}
};

window.addEventListener("resize", handleResize);
handleResize();

return () => {
window.removeEventListener("resize", handleResize);
};
Expand All @@ -40,23 +41,30 @@ const MovieBackground = ({
<section
className={`flex flex-col relative pt-[80px] after:content-[''] after:absolute after:inset-0 after:z-[1] after:bg-gradient after:h-[85vh]`}
>
<div className="w-full top-0 right-0 h-[85vh] absolute z-[1]">
<div className='w-full top-0 right-0 h-[85vh] absolute z-[1]'>
<img
src={movies?.[currentIndex].poster_path ? backgroundImage: '/noImage.avif'}
src={
movies?.[currentIndex].poster_path
? backgroundImage
: "/noImage.avif"
}
alt={movies?.[currentIndex]?.title}
className='absolute z-[1] top-0 w-[100vw] right-0 h-[85vh] min-w-full object-cover saturate-[1.2]'
onLoad={(e) => {
e.target.style.opacity = 1;
e.target.style.opacity = 1;
}}
style={{ opacity: 0, transition: 'opacity 0.5s' }}
style={{ opacity: 0, transition: "opacity 0.5s" }}
/>
</div>

<div className='px-8 md:px-10 lg:px-12 2xl:px-16 pb-8 z-10'>
<div
className={`flex flex-col gap-3 justify-end min-h-homeSpaceFondo lg:min-h-homeSpaceFondoPC`}
>
<h2 className='text-white text-[1.875rem] font-semibold lg:text-[40px]'>
<h2
ref={title}
className='text-white text-[1.875rem] font-semibold lg:text-[40px]'
>
{movies?.[currentIndex]?.original_name}
</h2>
<ul className='flex text-xs movieId:text-sm gap-4 text-white lg:text-lg lg:gap-6'>
Expand All @@ -66,9 +74,17 @@ const MovieBackground = ({
</ul>
<span
className='mt-6 w-[40px]'
onClick={() =>
viewNavigate(movies?.[currentIndex].id, navigate)
}
onClick={() => {
title.current.classList.add("full-title");
document.startViewTransition(async () => {
title.current.style.viewTransitionName = "";
flushSync(() =>
navigate(
`/tv/${movies?.[currentIndex].id}`
)
);
});
}}
>
<CiPlay1
color='white'
Expand Down
24 changes: 17 additions & 7 deletions src/components/Home/MovieSlider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import "swiper/css";
import "swiper/css/pagination";
import "swiper/css/navigation";

import "../style/transition.css";

import { useEffect, useState } from "react";
import MovieBackground from "./MovieBackground";

Expand All @@ -16,6 +18,8 @@ import {
} from "react-icons/md";
import { useNavigate } from "react-router-dom";
import { viewNavigate } from "../../utils/animationNavigate";
import { flushSync } from "react-dom";
import { viewTransition } from "../../utils/viewTransition";

const MovieSlider = ({ movies, genres }) => {
const [currentIndex, setCurrentIndex] = useState(0);
Expand Down Expand Up @@ -94,7 +98,7 @@ const MovieSlider = ({ movies, genres }) => {
genreNamesByIds={genreNamesByIds}
navigate={navigate}
/>
<div className='px-8 md:px-10 lg:px-12 2xl:px-16 overflow-hidden'>
<div className='px-8 md:px-10 lg:px-12 2xl:px-16'>
<h2 className='text-white text-[1.2rem] z-20 relative font-semibold mb-3'>
Últimas series
</h2>
Expand All @@ -117,18 +121,24 @@ const MovieSlider = ({ movies, genres }) => {
prevEl: ".swiper-button-prev",
}}
modules={[Pagination, Navigation, Autoplay]}
className='mySwiper overflow-hidden'
className='mySwiper '
autoplay={{ delay: 4500 }}
>
{movies?.slice(0, showMovies).map((movie) => (
<SwiperSlide key={movie.id} className='w-full'>
<div className='w-full cursor-pointer'>
<div
onClick={(e) => {
viewTransition(`/tv/${movie.id}`, navigate, e)
}}
>
<img
src={movie?.poster_path ? `https://image.tmdb.org/t/p/w500/${movie?.poster_path}` : '/noImage.avif'}
src={
movie?.poster_path
? `https://image.tmdb.org/t/p/w500/${movie?.poster_path}`
: "/noImage.avif"
}
alt={movie.title}
className='h-auto w-[250px] sm:h-[270px] md:h-[280px] lg:w-[360px] object-contain rounded'
onClick={() => viewNavigate(`/tv/${movie.id}`, navigate)}
style={{viewTransitionName: `imagen${movie.id}`}}
className={`mix-blend-normal h-auto w-[250px] sm:h-[270px] md:h-[280px] lg:w-[360px] object-contain rounded`}
/>
</div>
</SwiperSlide>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Movie/BodyMovieForId.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const BodyMovieForId = ({ movie, path }) => {
return (
<div className='px-6 md:px-10 lg:px-12 2xl:px-16 mb-8 relative z-30 max-w-[1400px] mx-auto'>
<div className='w-full py-5'>
<h2 className='font-semibold text-titulo md:text-5xl md:mb-6'>
<h2 className='font-semibold text-titulo md:text-5xl md:mb-6 full-title'>
{path === "/movie" ? movie?.title : movie?.original_name}
</h2>
<div className=' mt-2 text-xs opacity-100 font-light flex gap-4 md:text-sm'>
Expand Down
49 changes: 26 additions & 23 deletions src/components/Movie/HeaderMovie.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import { FaRegPlayCircle } from "react-icons/fa";
import Porcentaje from "../Porcentaje";
import Ligth from "./Ligth";
import { useEffect, useState } from "react";
import "../style/transition.css";

const HeaderMovie = ({ movie, setPlaying }) => {
const [backgroundImage, setBackgroundImage] = useState(`https://image.tmdb.org/t/p/original/${movie?.backdrop_path}`)
const [backgroundImage, setBackgroundImage] = useState(
`https://image.tmdb.org/t/p/original/${movie?.backdrop_path}`
);

useEffect(() => {
if (movie) {
const handleResize = () => {

if (window.innerWidth >= 1024) {
setBackgroundImage(
`https://image.tmdb.org/t/p/original/${movie?.backdrop_path}`
Expand All @@ -19,56 +21,57 @@ const HeaderMovie = ({ movie, setPlaying }) => {
`https://image.tmdb.org/t/p/w780/${movie?.backdrop_path}`
);
}
}
};

window.addEventListener("resize", handleResize);
handleResize();

return () => {
window.removeEventListener("resize", handleResize);
};
}
}, [movie])
}, [movie]);

const bgImg = {
backgroundImage: `url(${backgroundImage})`,
};

const url = movie?.poster_path ? `https://image.tmdb.org/t/p/original${movie?.poster_path}` : ''
const url = movie?.poster_path
? `https://image.tmdb.org/t/p/original${movie?.poster_path}`
: "";

// desplegar trailer
const handleTrailer = () => {
setPlaying(true)
}
setPlaying(true);
};

return (
<header
style={ movie?.backdrop_path ? bgImg : {}}
style={movie?.backdrop_path ? bgImg : {}}
className='h-[46vh] sm:h-[50vh] md:h-[55vh] w-full min-w-full relative bg-cover bg-no-repeat bg-left'
>
<div className='bg-gradiant absolute top-0 left-0 w-full h-[101%] '></div>
{/* <Ligth img={url}/> */}
<div className="w-full relative h-[46vh] sm:h-[50vh] md:h-[55vh] max-w-[1400px] mx-auto">
<div className=': w-full relative h-[46vh] sm:h-[50vh] md:h-[55vh] max-w-[1400px] mx-auto'>
<img
className='absolute z-10 rounded bottom-4 left-6 w-[130px] movieId:w-[170px] sm:w-[200px] sm:bottom-4 sm:left-8 md:left-10 lg:w-[220px] xl:left-12 xl:w-[240px] object-contain 2xl:left-16'
src={movie?.poster_path ? `https://image.tmdb.org/t/p/w500/${movie?.poster_path}` : '/noImage.avif'}
className={`full-embed absolute z-10 rounded bottom-4 left-6 w-[130px] movieId:w-[170px] sm:w-[200px] sm:bottom-4 sm:left-8 md:left-10 lg:w-[220px] xl:left-12 xl:w-[240px] object-contain 2xl:left-16`}
src={`https://image.tmdb.org/t/p/w500/${movie?.poster_path}`}
alt={movie?.title}
onError={(e) => {
e.target.onError = null;
e.target.src = "/noImage.avif";
}}
style={{viewTransitionName: `imagen${movie?.id}`}}
/>
<div className='w-[50%] h-full ml-auto relative bottom-0'>
<div
<div
className='cursor-pointer opacity-70 hover:opacity-80 absolute sm:translate-y-1/2 sm:top-[40%] sm:-left-8 top-[65%] -translate-y-[65%] left-10 transition-all duration-300 hover:scale-110'
onClick={handleTrailer}
>
<FaRegPlayCircle size={60} color='white' className="sm:w-[72px] sm:h-[72px] md:w-[80px] md:h-[80px]" />
<FaRegPlayCircle
size={60}
color='white'
className='sm:w-[72px] sm:h-[72px] md:w-[80px] md:h-[80px]'
/>
</div>
</div>
<div className="absolute right-6 -bottom-6 md:right-10 md:-bottom-10 lg:right-12 xl:right-14 2xl:right-16 bg-gray-950 rounded-full">
<Porcentaje movie={movie}/>
<div className='absolute right-6 -bottom-6 md:right-10 md:-bottom-10 lg:right-12 xl:right-14 2xl:right-16 bg-gray-950 rounded-full'>
<Porcentaje movie={movie} />
</div>
</div>
</header>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Movie/Recomendaciones.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ const Recomendaciones = ({ similares, isMovie }) => {
<div className='relative'>
{/* Botón Controller */}
<SliderMovie movies={similares} isMovie={isMovie} nextEl={nextEl} prevEl={prevEl} pageId={true}/>
<div ref={nextEl} className={` swiper-button-next absolute top-[60%] -right-8 transform -translate-y-1/2 w-8 text-white opacity-80 after:content-none`}>
<span ref={nextEl} className={` swiper-button-next absolute top-[60%] -right-8 transform -translate-y-1/2 w-8 text-white opacity-80 after:content-none`}>
<MdOutlineKeyboardArrowRight
size={40}
/>
</div>
<div ref={prevEl} className={`swiper-button-prev absolute top-[60%] -left-8 transform -translate-y-1/2 w-8 text-white opacity-80 after:content-none`}>
</span>
<span ref={prevEl} className={`swiper-button-prev absolute top-[60%] -left-8 transform -translate-y-1/2 w-8 text-white opacity-80 after:content-none`}>
<MdKeyboardArrowLeft size={40} />
</div>
</span>
</div>
</div>
);
Expand Down
11 changes: 2 additions & 9 deletions src/components/Porcentaje.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,14 @@ const Porcentaje = ({ movie }) => {
const longitudDeRelleno = (`${percent}` / 100) * circunferencia;

return (
<div className='cursor-context-menu relative w-16 h-16 md:w-20 md:h-20 lg:w-24 lg:h-24 before:hover:opacity-100 before:transition-opacity before:opacity-0 before:text-xs before:rounded-sm before:py-1 before:px-2 before:bg-[#111] before:right-1/2 before:translate-x-1/2 before:-top-14 before:absolute before:content-["Puntuación_de_usuario"]'>
<div className='relative w-16 h-16 md:w-20 md:h-20 lg:w-24 lg:h-24 before:hover:opacity-100 before:transition-opacity before:opacity-0 before:text-xs before:rounded-sm before:py-1 before:px-2 before:bg-[#111] before:right-1/2 before:translate-x-1/2 before:-top-14 before:absolute before:content-["Puntuación_de_usuario"]'>
<svg
width='100%'
height='100%'
viewBox={`0 0 ${2 * radio} ${2 * radio}`}
xmlns='http://www.w3.org/2000/svg'
className="stroke-[5] lg:stroke-[6]"
className="stroke-[5] lg:stroke-[6] "
>
<circle
cx={radio}
cy={radio}
r={radio - 2}
fill='transparent'
stroke='#050b1b'
/>
<circle
cx={radio}
cy={radio}
Expand Down
4 changes: 2 additions & 2 deletions src/components/SliderMovie.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "swiper/css/pagination";
import { useNavigate } from "react-router-dom";
import { Navigation } from "swiper/modules";
import { viewNavigate } from "../utils/animationNavigate";
import { viewTransition } from "../utils/viewTransition";

const SliderMovie = ({ movies, isMovie, nextEl, prevEl, pageId }) => {
const navigate = useNavigate();
Expand Down Expand Up @@ -58,8 +59,7 @@ const SliderMovie = ({ movies, isMovie, nextEl, prevEl, pageId }) => {
e.target.src = "/noImage.avif";
e.target.style.pointerEvents = "none";
}}
onClick={() => viewNavigate(`${isMovie}/${movie.id}`, navigate)}
style={{viewTransitionName:`image${movie.id}`}}
onClick={(e) => viewNavigate(`${isMovie}/${movie.id}`, navigate)}
/>
</div>
</SwiperSlide>
Expand Down
20 changes: 20 additions & 0 deletions src/components/style/transition.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.full-embed {
view-transition-name: full-embed;
}

.full-title {
view-transition-name: full-title;
}
::view-transition-old(full-embed){
mix-blend-mode: normal;
animation-duration: 0.3s;
}
::view-transition-new(full-embed) {
animation: none;
mix-blend-mode: normal;
}

::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.3s;
}
15 changes: 7 additions & 8 deletions src/pages/MovieForId.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,27 @@ const MovieForId = ({ path }) => {
// Desplegar trailer
const [playing, setPlaying] = useState(false);

if (loading || loadingProviders || loadingCredits || loadingSimilarMovie) {
return (
<LoadingMovie/>
)
}
// if (!movie || loading || loadingProviders || loadingCredits || loadingSimilarMovie) {
// return <LoadingMovie />;
// }


return (
<article className='text-white'>
{/* header */}
<HeaderMovie movie={movie} setPlaying={setPlaying} />

{/* BODY */}
<BodyMovieForId movie={movie} path={path}/>
<BodyMovieForId movie={movie} path={path} />

{/* Categorias */}
<Categorias movie={movie}/>
<Categorias movie={movie} />

{/* Homepage */}
{movie?.homepage.length > 0 && (
<div className='px-6 md:px-10 lg:px-12 2xl:px-16 mt-8 flex items-center gap-16 max-w-[1400px] mx-auto'>
<a href={movie?.homepage} className='block w-[180px]'>
<Button text='Home Page' noNavigate={true}/>
<Button text='Home Page' noNavigate={true} />
</a>
</div>
)}
Expand Down
3 changes: 1 addition & 2 deletions src/utils/animationNavigate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import { flushSync } from "react-dom";

export const viewNavigate = (nuevaRuta, navigate, isLoading) => {
if (isLoading) return;
export const viewNavigate = (nuevaRuta, navigate) => {
window.scroll(0, 0);
if (!document.startViewTransition) {
return navigate(nuevaRuta);
Expand Down
11 changes: 11 additions & 0 deletions src/utils/viewTransition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { flushSync } from "react-dom";

export const viewTransition = (ruta, navigate, e) => {
const element = e.target;
element.classList.add("full-embed");

document.startViewTransition(async () => {
element.style.viewTransitionName = "";
flushSync(() => navigate(ruta));
});
};
Loading

0 comments on commit d65b9a6

Please sign in to comment.