18910140161

react.js中带有canvas元素的JavaScript-Timer与PictureInPicture-Stack溢出

顺晟科技

2022-10-19 12:21:46

234

我试图通过使用画布和PictureInPicture在React中创建一个计时器,这样每当用户关闭窗口时,它将继续在后台或桌面屏幕上运行。 但不管用。记住它应该在react中。我在HTML Javascript中尝试过,它工作得很好,但在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 

× 未处理的拒绝(TypeError):无法读取未定义的属性(读取“HAS Attribute”)

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 

顺晟科技:

  • TAG:
相关文章
我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航