mardi 21 septembre 2021

Timer with canvas element in React.js with PictureInPicture

I am trying to create a Timer in React by using Canvas and PictureInPicture so that whenever the user closes the window it will keep running in the background or on Desktop Screen. But It's not working. Remember it should be in React.I tried in HTML Javascript and it works well but it's not happening in React.js

import { React, useState, useRef, useEffect } from "react";
import {FaPauseCircle} from 'react-icons/fa'
import {AiFillPlayCircle} from 'react-icons/ai'
import {BsFillPipFill} from 'react-icons/bs'   //importing icons 
import './timer.scss'
//import { render } from '@testing-library/react'


function Timer() {
  const videoElement = useRef();
  const [icon, setIcon] = useState(false);   //setting icon state   false as default 
  const [timerFlag, setTimerFlag] = useState(false);
  const [isDisabled, setIsDisabled] = useState(false); 
  const [totalSeconds, setTotalSeconds] = useState(0);

  const anim = (source, ctx) => {                               //  creating a  ctx as object for canvas and saving it to a variable. This is where  we’ll actually be drawing on.
    console.log('>>>', ctx)
    // error detected 
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, source.width, source.height);
    ctx.fillStyle = "white";
    ctx.fillText( output(), source.width / 2, source.height / 2 );
    //window.requestAnimationFrame(anim);
 }

  const init = () => {
    
     const videoElement = document.createElement('video');
    const source = document.createElement('canvas');
    const ctx = source.getContext('2d'); 
    ctx.font = "50px Arial";
    ctx.textAlign = "center";         
    ctx.textBaseline = "middle";
    console.log('>>', ctx)                 
    anim(source, ctx);
    const stream = source.captureStream();
    //videoElement. srcObject= stream;
    console.log('SOURRRR', source);
  }

  const openPictureInPicture = async (videoElement) => {
    if (!videoElement.hasAttribute('isPip')) {                               // PictureinPicture videoElementting 
        await videoElement.requestPictureInPicture();
        videoElement.setAttribute('isPip', true);
        videoElement.addEventListener('leavepictureinpicture', event => {
            videoElement.removeAttribute('isPip')
        }, {
            once: true
        })
    } else {
        await document.exitPictureInPicture();    
    }
  }


    function pad(val) {
        var valString = val + "";
        if (valString.length < 2) {                             
            return "0" + valString;   //Timer mentionin 00:00:00))
        } else {
            return valString;
        }
    }

    
    const buttonClick = (e, videoElement) => {
      if( <videoElement className="requestPictureInPicture"></videoElement> ) {
          openPictureInPicture(videoElement);
          }
          else {                                 // videoElementting the PictureinPicture  when we move from screen to screen 
              setIsDisabled(true);
          }
      }

    function timerSwitch() {
        var myDate = new Date();
        console.log(myDate.toLocaleTimeString('en-US'))
        setTimerFlag(!timerFlag); 
        if (timerFlag) {                            
            setIcon(true);
        }else {
            setIcon(false);         //Here the timer is getting Started when we click on Button to start the timer 
        }
    }

    function output() {                        // 
      let result = null;
      if (totalSeconds === 0) {  //Initially setting timer setting to  00:00:00 
          result = "00:00:00";
      }else {
          result = pad(parseInt(totalSeconds / (60 * 60))).toString() + ":" + pad(parseInt((totalSeconds % (60 * 60) / 60))).toString() + ":" + pad(totalSeconds % 60).toString();
      }       //Here , Calculation of  timing  is done where actual timer is performing 
      return result;
  }
    
    useEffect(() => {
        init();

        setInterval(function() {                     //Everytime timer is updated every second ..
            if (timerFlag) {                             
                setTotalSeconds(++totalSeconds);
            }
        }, 1000);
         // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [])



  return (
    <div className="timer-container ">
     
      {/* <video ref={videoElement} muted autoPlay height="100px" width="100px"></video>  Here By using Video PictureInPicutre is being videoElementted to call  */}
      <button
        className="stop-start"
        onClick={() => {
            timerSwitch();                        
        }}
        type="button"
      >
        {icon ? <AiFillPlayCircle /> : <FaPauseCircle />}
      </button>

      <button className="pip" disabled={isDisabled} onClick={(e) => buttonClick(e)}>  
      <BsFillPipFill />     {/*   By Default PIP is disabled until we click to stat its functionality  */}
      </button>

    </div>
  );
}

export default Timer; ```

Here is the Output 

× Unhandled Rejection (TypeError): Cannot read properties of undefined (reading 'hasAttribute')

   const buttonClick = (e, videoElement) => {
     if( <videoElement className="requestPictureInPicture"></videoElement> ) {
         **openPictureInPicture(videoElement);**//here is the another error 
         }
         else {                                 // videoElementting the PictureinPicture  when we move from screen to screen 
             setIsDisabled(true);
         }
     }



Aucun commentaire:

Enregistrer un commentaire