Vimeo, detect fullscreen to block fetching of new player (dynamic width changes)

落花浮王杯 提交于 2020-04-18 06:31:10

问题


I want to dynamically change the width of my vimeo player adapting to the window width. You can see the full code of the component at the end of the question and maybe there is already a way simpler approach to dynamically change the width of the player so I don't have to deal with the issues at all (The responsive option provided by vimeo does not work for me).

The issue I am having with my current solution: I don't want to trigger a change if the player goes into fullscreen or rotates the phone on fullscreen since vimeo already handles those changes automatically but I have a hard time to detect if the player is in fullscreen.

    const isFullscreen = (document.fullscreenElement
      || document.webkitFullscreenElement
      || document.mozFullScreenElement
      || document.msFullscreenElement
      || playerWidth === delayedWidth)

This solution breaks for iphone 11 pro and probably all Safari browsers since fullScreen is not fully implemented there.

import React, {
  useEffect, useContext, useState, useRef,
} from 'react';
import PropTypes from 'prop-types';
import Player from '@vimeo/player';

import STYLES from '../../enums/styles';
import { BrowserContext } from '../../contexts/BrowserContext';

const TAG = 'player';

/**
 * remove event listeners
 * @param {object} playerRef
 */
function removeEventListeners(playerRef) {
  if (!playerRef.current) return;
  playerRef.current.off('ended');
  playerRef.current.off('pause');
  playerRef.current.off('play');
}

/**
 * remove interval
 * @param {object} intervalRef
 */
function removeInterval(intervalRef) {
  if (!intervalRef.current) return;
  window.clearInterval(intervalRef.current);
}

/**
 * 640×480, 800×600, 960×720, 1024×768, 1280×960,
 * 1400×1050, 1440×1080 , 1600×1200, 1856×1392, 1920×1440, and 2048×1536
 * @param {} width
 */
function computeRatio(delayedWidth) {
  const height = window.innerHeight;
  const width = delayedWidth - delayedWidth * 0.1;

  if (height <= 480) {
    return width > 640 ? 640 : width;
  }
  if (height <= 600) {
    return width > 800 ? 800 : width;
  }
  if (height <= 720) {
    return width > 960 ? 960 : width;
  }
  if (height <= 768) {
    return width > 1024 ? 1024 : width;
  }
  if (height <= 960) {
    return width > 1280 ? 1280 : width;
  }
  if (height <= 1050) {
    return width > 1400 ? 1400 : width;
  }
  if (height <= 1080) {
    return width > 1440 ? 1440 : width;
  }
  if (height <= 1200) {
    return width > 1600 ? 1600 : width;
  }
  if (height <= 1392) {
    return width > 1856 ? 1856 : width;
  }
  if (height <= 1440) {
    return width > 1920 ? 1920 : width;
  }
  if (height <= 1536) {
    return width > 2048 ? 2048 : width;
  }
  return width;
}

const VideoPlayer = ({
  index, title, description, link, onProgress, latestProgress,
}) => {
  const { delayedWidth } = useContext(BrowserContext);
  const [time, setTime] = useState(latestProgress < 1 ? latestProgress : 0);
  const playerRef = useRef(null);
  const intervalRef = useRef(null);

  useEffect(() => {
    console.tag(TAG).debug('changing delayed width', delayedWidth);

    const asyncEffect = async () => {
      const player = playerRef.current;
      if (player) {
        const playerWidth = await player.getVideoWidth();
        const isFullscreen = document.fullscreenElement
        || document.webkitFullscreenElement
        || document.mozFullScreenElement
        || document.msFullscreenElement
        || playerWidth === delayedWidth;
        console.tag(TAG).debug('fullscreen detected', isFullscreen);

        const isMobile = window.innerWidth <= STYLES.breakpoints.phoneWidth;
        const isLandscape = window.innerWidth > window.innerHeight;

        if (isFullscreen || (isLandscape && isMobile)) {
          console.tag(TAG).debug('isLandscape, isMobile', isLandscape, isMobile);
          return;
        }

        removeEventListeners(playerRef);
        playerRef.current = null;
        player.pause();
        player.destroy();
      }

      if (intervalRef.current) {
        removeInterval(intervalRef);
        intervalRef.current = null;
      }

      const options = { id: link, width: computeRatio(delayedWidth) };
      const newPlayer = new Player(`frame-${title}-${index}`, options);
      playerRef.current = newPlayer;

      if (time) {
        newPlayer.getDuration().then((duration) => {
          const seconds = duration * time;
          newPlayer.setCurrentTime(seconds);
        });
      }

      const keepTrackProgress = async () => {
        // gets duration of video in seconds
        const duration = await newPlayer.getDuration();

        intervalRef.current = window.setInterval(() => {
          newPlayer.getCurrentTime().then((seconds) => {
            // `seconds` indicates the current playback position of the video
            const progress = seconds / duration;
            console.tag(TAG).debug(`progress: ${progress}, duration ${duration}, seconds ${seconds}`);
            onProgress(progress);
            setTime(progress);
          });
          // track every next 10 seconds of progress
        }, 10000);
      };

      newPlayer.on('ended', () => {
        removeInterval(intervalRef);
        intervalRef.current = null;
        onProgress(1);
        setTime(1);
      });

      newPlayer.on('pause', ({ duration, seconds }) => {
        removeInterval(intervalRef);
        intervalRef.current = null;
        const progress = seconds / duration;
        console.tag(TAG).debug(`progress at paused: ${progress}, duration ${duration}, seconds ${seconds}`);
        onProgress(progress);
        setTime(progress);
      });

      newPlayer.on('play', () => {
        keepTrackProgress();
      });
    };

    asyncEffect();
    return () => {
      removeInterval(intervalRef);
      removeEventListeners(playerRef);
    };
  }, [delayedWidth]);

  return (
    <div className="video-player">
      <div id={`frame-${title}-${index}`} className="frame-wrapper" />
      <div className="details">
        <h1>{title}</h1>
        <p>{description}</p>
      </div>
    </div>
  );
};


VideoPlayer.propTypes = {
  index: PropTypes.number.isRequired,
  title: PropTypes.string.isRequired,
  description: PropTypes.string.isRequired,
  link: PropTypes.string.isRequired,
  onProgress: PropTypes.func.isRequired,
  latestProgress: PropTypes.number.isRequired,
};

export default VideoPlayer;


回答1:


I'm using u-wave vimeo player, where the responsive has been taken care.

import Vimeo from '@u-wave/react-vimeo';`

<Vimeo
    video={videoURL}
    autoplay={false}
    controls={true}
    responsive={true}
    onEnd={() => { onVideoEnd() }}
    style={{ justifyContent: 'center'}}
    start={0}
    onTimeUpdate={(duration) => { console.log(duration }} />


来源:https://stackoverflow.com/questions/60921169/vimeo-detect-fullscreen-to-block-fetching-of-new-player-dynamic-width-changes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!