Malik Usman
Malik Usman

Reputation: 21

Video play using Mouse Scroll or MouseTrackpad in REACT.js

React Developers, I am trying to achieve a functionality in REACT where I can play a limited part of the video using mouse scroll. Some how I came to a point where it is working. But still it's not working as expected. The functionality that I want to achieve is here: Open Link Here

Functionality Detail: 1: When I scroll down it plays few seconds of the video and it have to stop. 2: Scrolling up will play another video which is made is backward direction. 3: Custom Clickable progress bar

I have tried to make the same thing but it's not working properly. It does not stay on Video component while i am scrolling. It play's the video with scroll but it also went a little bit down to third component. It should stay on the same component till all the segments of videos completed. Scroll back also not working when i come to third component and comes back to the video component the reverse scroll does not works.

Here is my code:

ScrollVideo.js

import React, { useRef, useEffect, useState } from 'react';
import styled from 'styled-components';
import ScrollVid from '../content/videos/ft.mp4';
import VidImage from '../content/images/vidcover.JPG';

const VideoWrapper = styled.div`
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;

  video {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
`;

const ProgressBar = styled.div`
  position: absolute;
  bottom: 0;
  left: 0;
  height: 5px;
  background: #fff;
  transition: width 0.3s ease;
  width: ${(props) => (props.$progress / 7) * 100}%;
`;

const ScrollVideo = () => {
  const videoRef = useRef(null);
  const containerRef = useRef(null);
  const [scrollIndex, setScrollIndex] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);
  const [isInView, setIsInView] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        const entry = entries[0];
        setIsInView(entry.isIntersecting);
      },
      { threshold: 0.8 }
    );

    if (containerRef.current) {
      observer.observe(containerRef.current);
    }

    return () => {
      if (containerRef.current) {
        observer.unobserve(containerRef.current);
      }
    };
  }, []);

  useEffect(() => {
    if (isInView) {
      const handleWheel = (event) => {
        event.preventDefault();
        if (isPlaying) return;

        const { deltaY } = event;
        const newScrollIndex = Math.min(
          8,
          Math.max(0, scrollIndex + (deltaY > 0 ? 1 : -1))
        );

        if (newScrollIndex !== scrollIndex) {
          setScrollIndex(newScrollIndex);
        }
      };

      window.addEventListener('wheel', handleWheel, { passive: false });

      return () => {
        window.removeEventListener('wheel', handleWheel);
      };
    }
  }, [isInView, isPlaying, scrollIndex]);

  useEffect(() => {
    const video = videoRef.current;

    if (video && scrollIndex > 0 && scrollIndex <= 7) {
      setIsPlaying(true);
      video.currentTime = (scrollIndex - 1) * 3;
      video.play();
      const timeout = setTimeout(() => {
        video.pause();
        setIsPlaying(false);
      }, 3000);
      return () => clearTimeout(timeout);
    } else if (scrollIndex === 8) {
      const nextSection = containerRef.current.nextElementSibling;
      if (nextSection) {
        setScrollIndex(9); // To ensure it doesn't keep transitioning
        nextSection.scrollIntoView({ behavior: 'smooth' });
      }
    } else if (scrollIndex === 0) {
      const prevSection = containerRef.current.previousElementSibling;
      if (prevSection) {
        prevSection.scrollIntoView({ behavior: 'smooth' });
      }
    }
  }, [scrollIndex]);

  return (
    <VideoWrapper ref={containerRef}>
      <video
        ref={videoRef}
        muted
        preload="metadata"
        poster={VidImage}
        playsInline
        className="w-full h-auto object-cover"
      >
        <source src={ScrollVid} type="video/mp4" />
      </video>
      <ProgressBar $progress={scrollIndex} />
    </VideoWrapper>
  );
};

export default ScrollVideo;

App.js

import React from 'react';
import Header from './components/Header';
import HeroSection from './components/HeroSection';
import SecondSection from './components/SecondSection';
import Specs from './components/SpecsTruck'
import Scroll from './components/ScrollVideo'
import Vid from './components/FullpageWithVideos'
import './style.css'

function App() {
  return (
    <div style={{ backgroundColor: 'black', color: 'white' }}>
      <Header />
      <HeroSection />
      <Vid/>
      <Scroll/>
      <SecondSection />
      <Specs/>
    </div>
  );
}
export default App;

Style.css

.video-section {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.video-section video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.progress-bar {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 5px;
  background: #fff;
  transition: width 0.3s;
}

Upvotes: 0

Views: 23

Answers (1)

Alvaro
Alvaro

Reputation: 41595

More than a React question this is a JavaScript one.

Here's how to do it:

      var video = document.querySelector('.video');

      // Play the video
      video.play();

      // Stop the video after 3 seconds
      setTimeout(function() {
          video.pause();
      }, 3000);

And if you use fullpage.js, then you can use the beforeLeave callback.

Here's a simple demo: https://codepen.io/alvarotrigo/pen/ZEdrOaW

And the code:


new fullpage('#fullpage', {
  sectionsColor: ['yellow', 'orange', '#C0C0C0', '#ADD8E6'],
  beforeLeave: function(origin, destination, direction, trigger){
    if(origin.index === 0){
      var video = document.querySelector('.video');

      // Play the video
      video.play();

      // Set a timeout to stop the video after 2 seconds
      setTimeout(function() {
          video.pause();          // Pause the video
      }, 3000);
    }
    return false;
  },
  
  // Get your license at https://alvarotrigo.com/fullPage/pricing/
  licenseKey: 'YOUR LICENSE KEY HERE '
});

Upvotes: 0

Related Questions