Необходимо отображать видеоконтроль HTML5 при наведении или воспроизведении

Я хотел бы скрыть элементы управления для нескольких HTML5-видео на странице. Если пользователь наводил курсор на видео, должны отображаться элементы управления. Если они нажимают кнопку воспроизведения, элементы управления должны оставаться видимыми, даже если их мышь покидает элемент видео.

Я не могу заставить это работать, используя следующий код. Может ли кто-нибудь выявить проблему?

var $video = $('.video');

$video.on('mouseover', show);
$video.on('mouseleave', hide);

function show() {
  $(this).attr('controls', '');
}

function hide() {
  var isPlaying = false;

  this.onplaying = function() {
    isPlaying = true;
  }

  if (!isPlaying) {
    $(this).removeAttr('controls');
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<video class="video">
  <source src="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4" type="video/mp4">
</video>

Ответ 1

Мы не можем контролировать это поведение, поскольку он управляется браузером. Все, что мы можем сделать, это указать атрибут controls, а браузер сделает все остальное.

Например: в Firefox (v59b, когда это написано) элементы управления будут исчезать, когда мышь находится вне элемента, когда воспроизводится видео, даже если установлен атрибут controls - они будут отображаться, если не воспроизводятся, наоборот, вы после. Невозможно заставить элементы управления оставаться видимыми, когда пользователь перемещает мышь вне видеоэлемента.

Единственный способ правильно обработать этот кросс-браузер и с точным желаемым поведением - создать пользовательский интерфейс пользовательских элементов управления для проигрывателя. Это, конечно, означает, что для обработки различных событий требуется больше кода, чтобы вы могли обновлять и управлять пользовательским интерфейсом; это также может быть проблемой, когда речь заходит о конкретном взгляде на платформу/браузер. Но это, с другой стороны, даст вам контроль над зерном.

Альтернативой является просмотр некоторых библиотек, которые обертывают элемент видео в пользовательские элементы управления пользовательским интерфейсом и видят, позволяют ли они заставить элементы управления оставаться видимыми при заданных условиях. В качестве отправной точки смотрите videojs.

Небольшой, но неполный пример (добавьте функциональность, обработчики событий, при необходимости создайте):

var $container = $("#video1");
var $video = $container.children("video"), video = $video[0]
var $controls = $container.children(".controls");
var $play = $controls.children("button");

// control visibility
$container.on("mouseover mouseout", function(e) {
  $controls.css("display", e.type === "mouseout" && video.paused ? "none" : "block");
});

// play or pause
$play.on("click", toggle);
$video.on("click", toggle);

function toggle() {
  video[video.paused ? "play" : "pause"]();
}

// todo: cover more events (seeked, error etc.)
$video.on("play pause ended", updateUI);

// update control UI elements (todo: update time/progress etc.)
function updateUI() {
  $play.text(video.paused ? "Play" : "Pause")
}
.container {
  position:relative;
  display:inline-block;
  font-size:0;
  }
.container > .controls {
  position:absolute;
  bottom:0;
  width:100%;
  background:rgba(255,255,255,0.3);
  padding:7px;
  box-sizing:content-box;
  z-index:10000;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=video1 class=container>
  <video width=640 muted src="//media.w3.org/2010/05/sintel/trailer.mp4"></video>
  <div class=controls style="display:none">
    <button>Play</button>
  </div>
</div>

Ответ 2

Проверьте этот код. его работа в соответствии с вашими требованиями. использовать "$ ('. video" ). get (0).paused "function in if условие для установки isplaying = True.

var $video = $('.video');

$video.on('mouseover', show);
$video.on('mouseleave', hide);

function show() {
  $(this).attr('controls', '');
}

function hide() {
  var isPlaying = false;
  if(!$('.video').get(0).paused) {
    isPlaying = true;
  }
  if (!isPlaying) {
    $(this).removeAttr('controls');
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<video class="video">
  <source src="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4" type="video/mp4">
</video>

Ответ 3

Независимо от того, что вы установили в обработчике onplaying, вы по-прежнему устанавливаете isPlaying как false при каждом выполнении show(), чтобы он всегда удалял элементы управления. Попытайтесь немного изменить свою логику. Как и ручка, когда видео останавливается, приостанавливается или иным образом изменяется состояние. Используйте те, чтобы изменить свою логику, показывая элементы управления.

Ответ 4

Обновлено - единственным решением для браузера является пользовательский контроль

Элементы управления Chrome и Firefox видны при наведении и воспроизведении. В качестве бонусного бонуса он реагирует. Примечание. Если вы хотите, чтобы он правильно функционировал для Firefox и Chrome в полноэкранном режиме, см. Plunker 🟊.

Похоже, что при воспроизведении видео не удается отображать элементы управления, если не запущено событие mousemove. Сначала я понял, что если бы мы могли перемещать мышь 1px туда и обратно, это было бы решением, хотя и хакерским и ресурсоемким. К сожалению, перемещение курсора мыши программно невозможно, потому что никто не очень ценит, что их мышь захвачена, независимо от того, насколько невиновны намерения разработчика.

Сначала я думал, что .focus() будет работать, но не для Firefox, поэтому, пытаясь найти решение для простого кроссбраузерного поведения, оно сводилось к полностью удалению элементов управления и созданию настраиваемых элементов управления. Он включает в себя тонну специальных стилей, характерных для каждого браузера. См. Эту статью: Создание пользовательского видеопроигрывателя HTML5 и DOM DOM. Следующая демо - это многопользовательская версия jQuery статьи демо. Подробнее см. README.md.

Plunker 🟊

Демо - пользовательские элементы управления - Примечание: Firefox и Chrome в полноэкранном режиме см. Plunker 🟊.

<!DOCTYPE html>
<html>

<head>
  <meta charset='utf-8'>

  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
  <style>
  html {
    box-sizing: border-box;
  }
  
  *,
  *::before,
  *::after {
    box-sizing: inherit;
  }
  
  body {
    padding: 0;
    display: flex;
    flex-flow: column nowrap;
    min-height: 100vh;
    background: linear-gradient(135def, #7c1599 0%, #921099 48%, #7e4ae8 100%);
    background-size: cover;
    align-items: center;
    justify-content: center;
  }
  
  .cover {
    max-width: 750px;
    border: 5px solid rgba(0, 0, 0, 0.2);
    box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
    position: relative;
    font-size: 0;
    overflow: hidden;
  }
  
  .video {
    width: 100%;
  }
  
  .toggle {
    background: none;
    border: 0;
    line-height: 1;
    color: white;
    text-align: center;
    outline: 0;
    padding: 0;
    cursor: pointer;
    max-width: 50px;
  }
  
  .toggle:focus {
    border-color: #ffc600;
  }
  
  .volume {
    width: 10px;
    height: 30px;
  }
  
  .panel {
    display: flex;
    position: absolute;
    bottom: 0;
    width: 100%;
    transform: translateY(100%) translateY(-5px);
    transition: all 0.3s;
    flex-wrap: wrap;
    background: rgba(0, 0, 0, 0.1);
    z-index: 2147483648;
    left: 0;
  }
  
  .cover:hover .panel,
  .panel.active {
    transform: translateY(0);
  }
  
  .panel:hover .progress,
  .panel.active .progress {
    height: 15px;
  }
  
  .panel > * {
    flex: 1;
  }
  
  .progress {
    flex: 10;
    position: relative;
    display: flex;
    flex-basis: 100%;
    height: 5px;
    transition: height 0.3s;
    background: rgba(0, 0, 0, 0.5);
    cursor: ew-resize;
  }
  
  .bar {
    width: 50%;
    background: #ffc600;
    flex: 0;
    flex-basis: 50%;
  }
  /* unholy css to style input type="range" */
  
  input[type=range] {
    -webkit-appearance: none;
    background: transparent;
    width: 100%;
    margin: 12px 3px;
  }
  
  input[type=range]:focus {
    outline: none;
  }
  
  input[type=range]::-webkit-slider-runnable-track {
    width: 100%;
    height: 5px;
    cursor: pointer;
    box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
    background: rgba(255, 255, 255, 0.8);
    border-radius: 1.3px;
    border: 0.2px solid rgba(1, 1, 1, 0);
  }
  
  input[type=range]::-webkit-slider-thumb {
    box-shadow: 0 0 0 rgba(0, 0, 0, 0), 0 0 0 rgba(13, 13, 13, 0);
    height: 1.5em;
    width: 1.5em;
    border-radius: 20px;
    background: #ffc600;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: -8px;
    box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
  }
  
  input[type=range]:focus::-webkit-slider-runnable-track {
    background: #ffc600;
  }
  
  input[type=range]::-moz-range-track {
    width: 100%;
    height: 3px;
    cursor: pointer;
    box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
    background: #fff;
    border-radius: 1.3px;
    border: 0.2px solid rgba(1, 1, 1, 0);
  }
  
  input[type=range]::-moz-range-thumb {
    box-shadow: 0px 0px 0px rgba(0, 0, 0, 0), 0px 0px 0px rgba(13, 13, 13, 0);
    height: 1.5em;
    width: 1.5em;
    border: 0;
    border-radius: 20px;
    background: #ffc600;
    cursor: pointer;
  }
  /* full screen button styling */
  
  .fullscreen {
    margin-right: 7px;
    background: none;
    border: 1px solid white;
    border: 0;
    line-height: 1;
    color: white;
    text-align: center;
    outline: 0;
    padding: 0 0 5px 0;
    cursor: pointer;
    max-width: 30px;
    font-size: 1.3rem;
  }
  /* Because video needed a defined hieght in order for object-fit: fill to work. */
  
  video {
    height: 100%;
    object-fit: fill;
  }
  /* hide the default Chrome video player styling */
  
  video::-webkit-media-controls-overlay-enclosure {
    display: none !important;
  }
  
  video::-webkit-media-controls-enclosure {
    display: none !important;
  }
  
  video::-webkit-media-controls {
    display: none !important;
  }
  /*  Needed to hide player controls in Safari Only */
  
  video::-webkit-media-controls-panel {
    display: none !important;
  }
  
  video::-webkit-media-controls-play-button {
    display: none !important;
  }
  
  video::-webkit-media-controls-current-time-display {
    display: none !important;
  }
  
  video::-webkit-media-controls-time-remaining-display {
    display: none !important;
  }
  
  video::-webkit-media-controls-timeline {
    display: none !important;
  }
  
  video::-webkit-media-controls-mute-button {
    display: none !important;
  }
  
  video::-webkit-media-controls-volume-slider {
    display: none !important;
  }
  
  video::-webkit-media-controls-fullscreen-button {
    display: none !important;
  }
  
  video::-internal-media-controls-download-button {
    display: none !important;
  }
  /* Firefox Shadow DOM Fix */
  
  *::-moz-list-bullet,
  *::-moz-list-number {
    display: none !important;
  }
  
  *::-moz-meter-bar {
    display: none !important;
  }
  
  :-moz-full-screen:not(:root)::backdrop {
    display: none !important;
  }
  
  *::backdrop {
    display: none !important;
  }
  
  :fullscreen:not(:root) {
    display: none !important;
  }
  /* New addition to removal of User Agent StyleSheet for Firefox. Removed dotted border around range. */
  
  input[type="range"]::-moz-focus-outer {
    border: 0;
  }
  </style>

</head>

<body>

  <div id='V0' class='cover'></div>

  <div id='V1' class='cover'></div>

  <div id='V2' class='cover'></div>

  <div id='V3' class='cover'></div>

  <template id='controls'>
    <div class="panel">
      <div class="progress">
        <div class="bar"></div>
      </div>
      <button class="toggle" title="Play/Pause">
        <i class="fa fa-play fa-3x"></i>
      </button>
      <input type="range" class="volume" min="0" max="1" step="0.05" value="0.70">
      <button class='fullscreen'>
        <i class='fa fa-expand fa-2x'></i>
      </button>
    </div>
  </template>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 
  <script>
var mp4 = ['005609.mp4', '005610.mp4', '005611.mp4', '005612.mp4'];
var webm = ['041157.mp4', '041153.mp4', '041154.mp4', '041156.mp4'];

function init(VMp4, VWebm) {

  var VArray = Array.from(document.querySelectorAll('.cover'));

  VArray.map(function(V, idx) {
    var ID = V.id;
    return players(ID, idx, VMp4, VWebm);
  });
}

function players(id, IDX, vMp4, vWebm) {

  var V = document.getElementById(id);
  console.log(V);

  var frag = document.createDocumentFragment();
  var tag = document.createElement('video');
  var src0 = document.createElement('source');
  var src1 = document.createElement('source');

  tag.classList.add('video');
  tag.controls = false;
  tag.width = '320';
  tag.style.background = '#000';
  tag.poster = `https://gincore.net/images/video-play-2.png`;
  // Set Paths
  var mUrl = `https://storage04.dropshots.com/photos6000/photos/1381926/20170326/`;
  var wUrl = `https://storage04.dropshots.com/photos7000/photos/1381926/20180214/`;
  src0.type = 'video/mp4';
  src1.type = 'video/webm';
  src0.src = mUrl + vMp4[IDX];
  src1.src = wUrl + vWebm[IDX];

  frag.appendChild(tag);
  tag.appendChild(src0);
  tag.appendChild(src1);

  V.appendChild(frag);

  var controls = document.querySelector('#controls').content;
  var clone = document.importNode(controls, true);
  V.appendChild(clone);
}

init(mp4, webm);


$(".cover").each(function() {
  
  var C = $(this)[0].id;
  
  var $ctl = $(this).find('.panel');
  var $vid = $(this).find('.video');
  var $tog = $(this).find('.toggle');
  var $prg = $(this).find('.progress');
  var $bar = $(this).find('.bar');
  var $vol = $(this).find('.volume');
  var $tfs = $(this).find('.fullscreen')

  var ctl = $ctl[0];
  var vid = $vid[0];
  var tog = $tog[0];
  var prg = $prg[0];
  var bar = $bar[0];
  var vol = $vol[0];
  var tfs = $tfs[0];

  function togglePlay() {
    var playPause = vid.paused ? 'play' : 'pause';
    vid[playPause]();
    $tog.find('.fa').toggleClass('fa-play fa-pause');
  }

  function updateVolume() {
    vid.volume = this.value;
  }

  function updateProgress() {
    var perc = (vid.currentTime / vid.duration) * 100;
    bar.style.flexBasis = `${perc}%`;
  }

  function seekTrack(e) {
    var seekTime = (e.offsetX / prg.offsetWidth) * vid.duration;
    vid.currentTime = seekTime;
  }

  var isFullScreen = function() {
    return !!(document.webkitFullscreenElement || document.mozFullScreenElement || document.fullscreenElement);
  };

  function toggleFS() {
    if (!isFullScreen()) {
      if (vid.requestFullscreen) {
        vid.requestFullscreen();
      } else if (vid.webkitRequestFullScreen) {
        vid.webkitRequestFullScreen();
      } else if (document.getElementById(C).mozRequestFullScreen) {
        document.getElementById(C).mozRequestFullScreen();
      } else if (vid.msRequestFullscreen) {
        vid.msRequestFullscreen();
      }
      $tfs.find('.fa').removeClass('fa-expand').addClass('fa-compress');
      $ctl.removeClass('active');
      $('.panel').css('z-index', '-1');
      $('#' + C + " .panel").css('z-index',"2147483648");
    } else {
      if (document.exitFullscreen) {
        document.exitFullscreen();
      } else if (document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
      } else if (document.mozCancelFullScreen) {
        document.mozCancelFullScreen();
      } else if (document.msCancelFullscreen) {
        document.msCancelFullscreen();
      }
      $tfs.find('.fa').addClass('fa-expand').removeClass('fa-compress');
      if (!vid.pause || !vid.ended) {
        $ctl.addClass('active');
      }
      $('.panel').css('z-index', '2147483648');
    }
  }

  function go() {
    $ctl.addClass('active');
    $tog.find('.fa').removeClass('fa-play').addClass('fa-pause');
  }

  function stop() {
    $ctl.removeClass('active');
    $tog.find('.fa').removeClass('fa-pause').addClass('fa-play');
  }

  $vid.on('click', togglePlay);

  $tog.on('click', togglePlay);

  $vid.on('timeupdate', updateProgress);

  $vid.on('playing', go);

  $vid.on('ended pause', stop);

  $vol.on('input', updateVolume);

  var mousedown = false;

  $prg.on('click', seekTrack);

  $prg.on('mousemove', function(e) {
    mousedown && seekTrack(e);
  });

  $prg.on('mousedown', function() {
    mousedown = true;
  });

  $prg.on('mouseup', function() {
    mousedown = false;
  });

  $tfs.on('click', toggleFS);

});
  </script>
</body>

</html>

Ответ 5

Может ли этот пример помочь. Элемент элементов управления является логическим:

    // by id video.
    document.getElementById("video1").controls = true; //show
    document.getElementById("video1").controls = false; //hide.

    //or all video by tag name:
   document.getElementsByTagName("video").controls = true; //show
   document.getElementsByTagName("video").controls = false; //hide.

Ответ 6

Вы можете сделать это довольно легко в любых браузерах на основе webkit. Ниже приведен пример автономного примера с встроенным js, включая поддержку доступа к клавиатуре.

Сохранение контроля во время игры является самым сложным аспектом. Это требует псевдоселекторов CSS или доступа к теневому домику медиаплеера. Если вам нужно поддерживать Firefox, вам может потребоваться изучить стиль тени (или создать пользовательские элементы управления).

video[controls]::-webkit-media-controls-panel {
  display: flex !important;
  opacity: 1 !important;
}

/* not required */
video { width: 15em; height: auto; }
/* /not required */
<video 
  src="https://cdn.jsdelivr.net/npm/[email protected]/video.mp4"
  type="video/mp4"
  onmouseover="dataset.over=true;controls=true"
  onmouseout="delete dataset.over;if(paused) controls=false;"
  onplay="controls=true"
  onpause="if(!dataset.over && !dataset.focus) controls=false"
  onfocusin="dataset.focus=true; controls=true"
  onfocusout="delete dataset.focus; if(paused) controls=false;"
></video>

<video src="https://cdn.jsdelivr.net/npm/[email protected]/video.mp4" type="video/mp4" onmouseover="dataset.over=true;controls=true" onmouseout="delete dataset.over;if(paused)controls=false;" onplay="controls=true" onpause="if(!dataset.over&&!dataset.focus)controls=false" onfocusin="dataset.focus=true; controls=true" onfocusout="delete dataset.focus;if(paused)controls=false;"></video>

Ответ 7

Я создал пример в fiddle. К сожалению, это работает только в браузерах на базе веб-браузера или Chrome, таких как Chrome и Safari.

Здесь также фрагмент:

var $video = $('.video');

$video.on('mouseover', show);
$video.on('mouseleave', hide);

$video.on('playing', function() {
  $video.isPlaying = true;
});

$video.on('pause abort', function() {
  $video.isPlaying = false;
});

function show() {
    if (!$(this).attr('controls'))
  	$(this).attr('controls', '');
}

function hide() {
  if (!$video.isPlaying) {
     if ($(this).attr('controls'))
    	$(this).removeAttr('controls');
  }
}
video[controls]::-webkit-media-controls-panel {
    display: flex !important;
    opacity: 1 !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<video class="video">
  <source src="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4" type="video/mp4">
</video>

Ответ 8

Супер легкий! Посмотрите мой JSFiddle, здесь.

<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script><video class=video><source src=http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4 type=video/mp4></video><style>video[controls]::-webkit-media-controls-panel{display:flex!important;opacity:1!important}</style><script>var $video=$(".video");$video.on("mouseover",function(){this.dataset.over=!0,this.controls=!0}),$video.on("mouseout",function(){delete this.dataset.over,this.paused&&(this.controls=!1)})</script>