【问题标题】:Prevent Firefox from moving after `.exitFullscreen()`防止 Firefox 在 `.exitFullscreen()` 之后移动
【发布时间】:2017-07-31 08:38:38
【问题描述】:

Firefox 在退出全屏<img> 后会出现这种行为(错误?),用户最终会看到位于用户刚刚全屏查看的<img> 上方的元素。总之我的问题是:

如何防止 Firefox 在退出全屏模式后向上滚动?

由于 SO 严格的安全措施,作为 Snippet 发布的 MCVE 无法运行,因此我提供了 plunker。所有细节都在 Snippet 和 Plunker 中注释。此外,我添加了一个简单的界面,不仅可以重现问题,还可以更改布局以测试不同的组合。感谢您宝贵的时间。

SNIPPET(不起作用 - 请改为查看此 plunker

/* Several attempts to use the .focus() method
|| and focus events did not work for me, neither
|| has tabindex and anchors. If it appears that
|| my implementation is wrong (a strong possibility)
|| please inform me.
*/
$('a').click(function(e) {
  var tgt = $(this).prev();
  fs(tgt[0]);
  $(this).focus();
});
/* This function is for the MCVE 
|| It enables the ~select~ to remove and re-insert
|| the test elements. By doing so, we can see
|| how the test elements behave in different
|| combinations. What I found out about FF is
|| that when exiting a full screened ~img~ that's
|| positioned last is that it will lose focus 
|| and the viewport is scrolled up to the element 
|| above it.
*/
$('#sel1').on('change', function(e) {
  var V = $(this).val();
  var first = $('#' + V).find(':first').attr('id');
  if ($('#' + V).hasClass('media')) {
    $('#' + V).fadeOut('#' + first);
  } else {
    $('#' + V).fadeIn('#' + first);
  }
  $('#' + V).toggleClass('media');
});

/* These 2 functions are responsible for 
|| full screen. Please inform me if there's a 
|| better way, or if anything is outdated. I
|| have researched the Fullscreen API and I
|| haven't found any updates of any use. I've
|| used these functions for the last 3 years
|| so maybe I might've missed something 
|| critical.
*/ // There's no ms prefixes because I'm not concerned about IE.

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

function fs(target) {

  if (!isFullScreen()) {
    if (target.requestFullscreen) {
      target.requestFullscreen();
    } else if (target.webkitRequestFullscreen) {
      target.webkitRequestFullscreen();
    } else if (target.mozRequestFullScreen) {
      target.mozRequestFullScreen();
    }
  } else {
    if (document.exitFullscreen) {
      document.exitFullscreen();
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen();
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();
    }
  }
}
/* These styles are here for the demo itself 
|| and are not a cause of the problem at hand
*/

* {
  margin: 0;
  padding: 0
}

body {
  font: 400 16px/1.3 Consolas;
  height: 100%;
  width: 100%;
  background: #333;
  color: #fed
}

a {
  margin: 0 auto 50px;
  display: block;
  width: 48px;
  height: 48px;
  text-align: center;
  cursor: pointer;
  background-size: contain;
}

.vid,
.img,
.gif,
.svg {
  display: block;
  margin: 20px auto;
}

.expand {
  background: url(http://imgh.us/expand_2.svg)no-repeat;
}

header {
  padding: 15px 10px;
  margin: 15px auto;
}

fieldset {
  border: 10px solid tomato;
  width: 20ch
}

legend {
  font-size: 1.2em;
}

dt {
  text-decoration: underline;
  font: 1.1em;
}

dd {
  margin-left: 20px
}

.note,
dt {
  color: #ffcc33
}

.demo {
  width: 450px;
  padding: 10px;
  counter-reset: step;
}

.demo li::before {
  counter-increment: step;
  content: "» " counter(step) ". ";
  text-indent: -150px;
  margin-left: 30px;
  color: cyan;
}

.fs:-webkit-full-screen {
  max-width: 100%;
  height: auto;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">
  <title>Prevent Firefox from Moving After .exitFullscreen()</title>
  <style>

  </style>
</head>

<body>
  <header>
    <dl>
      <dt>Objective</dt>
      <dd>Prevent Firefox from Moving After .exitFullscreen()</dd>
      <dt>Behavior</dt>
      <dd><b class='note'>Expected: </b>When exiting fullscreen mode, we should be at the same position that we were at before</dd>
      <dd><b class='note'>Experienced: </b>In FF, when exiting fullscreen mode, we are scrolled up as if the element above has a higher tab priority or more than likely is that tab index and focus are being ignored by FF.</dd>
      <dt>Question</dt>
      <dd><b><mark>How can I prevent Firefox from scrolling up after exiting fullscreen mode?</mark></b></dd>
    </dl>
  </header>
  <section>
    <ol class='demo'>
      <li>To reproduce issue, use the &lt;select&gt; to remove items C, D, E, and F.</li>
      <li>Next, fullscreen item B by clicking the icon below it.</li>
      <li>Then exit full screen mode by hitting <kbd>ESC</kbd>.</li>
      <li>Notice we have jumped up the page.</li>
    </ol>
  </section>
  <!--This ~select~ is for the MCVE - details are
commented below in the ~script~ block-->

  <section>
    <fieldset>
      <legend>Remove and Re-insert Elements</legend>
      <select id='sel1'>
         <option value="">----</option>
         <option value='A'>&lt;video&gt; src=MP4</option>
         <option value='B'>&lt;img&gt; src=PNG</option>
         <option value='C'>&lt;video&gt; poster=GIF</option>
         <option value='D'>&lt;img&gt; src=SVG</option>
         <option value='E'>&lt;div&gt; &amp;nbsp;</option>
         <option value='F'>&lt;iframe&gt; srcdoc="&lt;DIV&gt;&lt;div&gt;"</option>
      </select>
    </fieldset>

    <!--I tried using the ~a~nchors, -id-, -name-, and -tabindex- 
FF was ignoring my attempts to keep or get focus. Using named or 
id ~a~nchors failed since the distance between desired spot
and the spot FF ends up at is short.-->
    <div id='A' class='media'>
      <video id="vid1" class="vid fs" src="http://html5demos.com/assets/dizzy.mp4" controls></video>
      <a href='#/' class='expand' tab-index='1'></a>
    </div>
    <div id='B' class='media'>
      <img id='img1' class='img fs' src='http://imgh.us/Lenna.png'>
      <a href='#/' class='expand' tab-index='1'></a>
    </div>
    <div id='C' class='media'>
      <video id='gif1' class='gif fs' poster='http://imgh.us/gir_zim.gif' width='300' height='300'></video>
      <a href='#/' class='expand' tab-index='1'></a>
    </div>
    <div id='D' class='media'>
      <img id='svg1' class='svg fs' src='http://www.clker.com/cliparts/j/g/8/S/V/O/test.svg' width='auto' height='500'>
      <a href='#/' class='expand' tab-index='1'></a>
    </div>

    <!--Subjects E and F were added to see if a "dummy"
element were to be the last element so that FF
would exit fullscreen on the last ~img~ correctly.
I got mixed results.-->
    <div id='E' class='media'>
      <div id='div1' class='fs'>&nbsp;</div>
      <a href='#/' class='expand' tab-index='1' height='1' width='1'></a>
    </div>
    <div id='F' class='media'>
      <iframe id='ifm1' class='fs' srcdoc="<div style='color:lime'>iframe srcdoc</div><div style='color:cyan'>2 divs</div>" allowfullscreen></iframe>
      <a href='#/' class='expand' tab-index='1' height='1' width='1'></a>
    </div>
    <footer class='bottom'> </footer>
  </section>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
  <script>
  </script>
</body>

</html>

【问题讨论】:

  • 这是您要找的吗? stackoverflow.com/questions/29348278/…
  • @KeerthanaPrabhakaran 感谢您抽出宝贵时间发表评论。我阅读了这篇文章以及我希望从中获得的有希望的链接。不幸的是,他们都没有解决我在使用 Firefox 时在Plunker 中展示的问题。
  • 基本上可以在进入全屏前保存滚动条位置,退出全屏后再恢复。就我谷歌搜索而言,这似乎是网络视频播放器的常见问题。
  • @KeerthanaPrabhakaran 一个好主意,我添加了一个获取鼠标坐标的简单函数(虽然不是为了避免混淆),下一步我仍在考虑如何使用该信息来停止滚动。我喜欢使用滚动条而不是Y 的想法。如果您有任何值得回答的细节,那就太好了。 ??????
  • 您可以考虑向 bugzilla 提出问题,听起来确实是一个错误,即使 save pageYoffset 确实可以解决该问题。

标签: javascript jquery css firefox fullscreen


【解决方案1】:

最初定义变量。

var sx,sy;

进入全屏前保存滚动条位置

var d= document, r= d.documentElement, b= d.body;
sx= r.scrollLeft || b.scrollLeft || 0;
sy= r.scrollTop  || b.scrollTop  || 0;

当玩家退出全屏时,

window.scrollTo(sx,sy);

希望这会有所帮助!

【讨论】:

  • 无论有没有我的 coords 函数,我都无法让你的代码工作,但你的建议让我走上了正确的道路。在@Kaido 的评论中,链接到它的代码是成功的,我也明白为什么我无法让您或我的代码正常工作是因为我试图收听点击事件,而不是像 Kaido 成功完成的那样使用 onmozfullscreenchange 事件。 +1 这个好主意,谢谢。
  • 很高兴它有帮助!
【解决方案2】:

这个答案完全归功于@Kaido,如果 Kaido 发布答案,我会很容易地替换这个答案。

我使用滚动方法的尝试没有奏效,因为我正在监听点击事件,而我本应该监听 onmozfullscreenchange

Plunker

演示

<!DOCTYPE html>
<html>

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

  <title>Prevent Firefox from Moving After .exitFullscreen()</title>
  <style>
    button {
      display: block;
      padding: 0;
      width: 32px;
      height: 32px;
      text-align: center;
      cursor: pointer;
      background-size: contain;
    }
    
    .expand {
      background: url(http://imgh.us/expand_2.svg)no-repeat;
    }
  </style>
</head>

<body>

  <div id='A' class='media'>A
    <video id="vid1" class="vid fs" src="http://html5demos.com/assets/dizzy.mp4" controls></video>

  </div>
  <div id='B' class='media'>B
    <img id='img1' class='img fs' src='http://imgh.us/Lenna.png'>
    <button class='expand'></button>
  </div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
  <script>
    $('button').click(function(e) {
      e.preventDefault();
      var tgt = $(this).prev();
      fs(tgt[0]);

    });
    /* This function is for the MCVE 
    || It enables the ~select~ to remove and re-insert
    || the test elements. By doing so, we can see
    || how the test elements behave in different
    || combinations. What I found out about FF is
    || that when exiting a full screened ~img~ that's
    || positioned last is that it will lose focus 
    || and the viewport is scrolled up to the element 
    || above it.
    */

    $('#sel1').on('change', function(e) {
      var V = $(this).val();
      var first = $('#' + V).find(':first').attr('id');
      if ($('#' + V).hasClass('media')) {
        $('#' + V).fadeOut('#' + first);
      } else {
        $('#' + V).fadeIn('#' + first);
      }
      $('#' + V).toggleClass('media');
    });

    /* These 2 functions are responsible for 
    || full screen. 
    */ // There's no ms prefixes because I'm not concerned about IE.

    var isFullScreen = function() {
      return !!(document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement);
    }
    // SOLUTION XXXXXXXXXX]START[XXXXXXXXXXXXXXX
    var yOffset;
    document.onmozfullscreenchange = function() {
      if (!isFullScreen()) {
        window.scrollTo(0, yOffset);
      }

    };
    // SOLUTION XXXXXXXXXXX]END[XXXXXXXXXXXXXXXX
    function fs(target) {

      if (!isFullScreen()) {
        yOffset = pageYOffset;
        if (target.requestFullscreen) {
          target.requestFullscreen();
        } else if (target.webkitRequestFullscreen) {
          target.webkitRequestFullscreen();
        } else if (target.mozRequestFullScreen) {
          target.mozRequestFullScreen();
        }
      } else {
        if (document.exitFullscreen) {
          document.exitFullscreen();
        } else if (document.webkitExitFullscreen) {
          document.webkitExitFullscreen();
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen();
        }

      }
    }
  </script>
</body>

</html>

【讨论】:

    猜你喜欢
    • 2021-11-28
    • 2013-03-16
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 2018-05-31
    相关资源
    最近更新 更多