javascript - 在响应式网站中保持窗口调整大小时的页面 View

标签 javascript responsive-design scroll

情况:
假设我们正在阅读响应式页面下方某处的内容。还假设我们将浏览器窗口调整为较小的尺寸,并且上面的一些内容由于宽度较薄而向下延伸,从而使整个页面更长。然后,当我们调整大小时,我们正在查看的任何内容都会相应地向下推到页面上。

示例:
假设我们要查看 this page 中的 Helper 类 部分。 。然后缩小/扩大窗口足够的量,移动我们正在向下/向上读取当前 View 的位。

提示:
我们有什么办法可以解决这个问题吗? IE。当我们调整窗口大小时,无论页面上方的内容发生什么变化,都保持页面的当前 View 。

想法:
我想我们至少可以从 javascript 开始,并在窗口大小调整上放置一个事件。然后自动将页面滚动到事件触发时 View 中最顶部的元素。但是,我不知道这将如何影响性能,尤其是在较大的页面中。
还有引用当前 View 中最顶层元素的问题。我们当前 View 的顶部可能会切断某些元素的顶部部分,更不用说在页面内的任何点通常有超过 1 个元素彼此层叠。我提到的最顶层元素的概念不是很明确定义:(

在我看来,这不是一般的响应式设计问题,而是网络浏览器默认滚动行为的问题?或者也许我错过了一些当前行为是可取的情况。


编辑24

已更新fiddle (参见 fullscreen result )基于 Rick Hitchcock's solution的解决方案。

使用 jQuery:

//onresize:
var scrollAmount;

if (topNode.getBoundingClientRect().top >= 0) {
    scrollAmount = $(topNode).offset().top - topNode.getBoundingClientRect().top;
} else {
    scrollAmount = $(topNode.offset().bottom - topNode.getBoundingClientRect().bottom;
}
$(window).scrollTop(scrollAmount);

即使在相同的浏览器中, fiddle 的行为也有点奇怪,我使用免费托管上传了相同的脚本 here .
仍然需要合并 IE、Opera 和 Safari 的 elementFromPoint 修复。


编辑3

感谢里克·希区柯克的所有帮助。顺便说一句,欢迎来到 stackoverflow :)
讨论正在变成跨浏览器兼容性问题,因此我接受了您的答案,因为我们几乎已经得到了原始问题的答案。不过,我仍然会修复我的实现。重点是跨浏览器问题、topNode 标准和 topNode 截止处理。

边缘情况

在玩弄它时,我注意到当我们位于小视口(viewport)中的页面底部时,然后切换到更大的视口(viewport)(现在让我们假设一些原来位于我们现在看到的元素之上的元素由于更宽的视口(viewport)中的容器更短而进入视野),在这种情况下,窗口不能总是将 topNode 锁定到视口(viewport)的顶部,因为我们已经到达了滚动底部。但是切换回小视口(viewport)现在使用在切换期间进入视口(viewport)的新 topNode。
尽管这应该是从正在实现的行为中预料到的,但它仍然是滚动底部的一个奇怪的副作用。

我也会在适当的时候调查这个问题。最初,我想在更新 topNode 之前简单地添加对滚动底部的检查。 IE。当我们到达滚动底部时保留旧的 topNode 直到再次向上滚动。还不知道结果会如何。我也会确保看看 Opera 如何处理这个问题。

最佳答案

这是我想到的:

(function(){
   var topNode;

   window.onscroll=function() {
     var timer;
     (function(){
        clearTimeout(timer);
        timer= setTimeout(
                 function() {
                   var testNode;
                   topNode= null;
                   for(var x = 0 ; x < document.body.offsetWidth ; x++) {
                     testNode= document.elementFromPoint(x,2);
                     if(!topNode || testNode.offsetTop>topNode.offsetTop) {
                       topNode = testNode;
                     }
                   }
                 },
                 100
               )
      }
     )();
   }

   window.onresize=function() {
     var timer;
     (function(){
        clearTimeout(timer);
        if(topNode) {
          timer= setTimeout(function(){topNode.scrollIntoView(true)},10);
        }
      }
     )();
   }
 }
)();

如果有一个 window.onbeforeresize() 函数,这会更简单。

请注意,这没有考虑元素的 textNode 的滚动位置。如果只调整窗口的高度,我们就可以处理这个问题。但调整宽度通常会导致重新格式化。

这适用于 Chrome、Firefox、IE 和 Safari。

编辑

它是如何工作的

代码的闭包使变量成为私有(private)的,并且计时器防止代码在滚动/调整大小期间不断运行。但两者都容易混淆代码,所以这里有另一个版本,可能有助于理解。请注意,IE 中需要 onscroll 计时器,因为 elementFromPoint returns null when it used in onscroll event .

var topNode;

window.onscroll=function() {
  setTimeout(
    function() {
      var testNode;
      topNode= null;
      for(var x = 0 ; x < document.body.offsetWidth ; x++) {
        testNode= document.elementFromPoint(x,2);
        if(!topNode || testNode.offsetTop>topNode.offsetTop) {
          topNode = testNode;
        }
      }
    },
    100
  )
}

window.onresize=function() {
  if(topNode) {
    topNode.scrollIntoView(true)
  }
}

topNode 在窗口滚动时维护屏幕最顶层的元素。

该函数沿着第三行从左到右扫描屏幕:document.elementFromPoint(x,2) *

它不会沿着第一行扫描,因为当 IE scrollIntoView 时,它会将元素向下推几个像素,使最上面的屏幕元素成为上一个元素 元素。 (通过反复试验弄清楚了这一点。)

调整窗口大小时,它只是将 topNode 定位在屏幕顶部。

[*最初,onscroll 沿着第 11 行(以像素为单位)从左到右扫描,直到找到只有一个子元素的元素。子节点通常是一个 textNode,但情况并非总是如此。示例:

<div><ul><li>...<li>...<li>...</ul></div>

div 只有一个子元素 - ul。如果窗口滚动到第 50 个 li,则由于 li 的固有填充,从左到右扫描将错误地返回 div

原代码已更新。 ]

关于javascript - 在响应式网站中保持窗口调整大小时的页面 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25137783/

相关文章:

css - 在所有设备上输入文本宽度不是 100% 响应

JavaScript 将许多函数括起来

javascript - 在特定条件下为对象附加值?

html - 使用 CSS 保持 div 的纵横比

html - 一个文档可以有超过 1 个响应式 CSS 样式表吗?如果是这样,如何?

javascript - 带有对象引用选择器的 jQuery parents()

jquery - 如何将缩略图滚动到站点

javascript - 无法向下滚动对话框并双击文件夹

javascript - Chrome 扩展 : sendMessage from content to background getting response from popup

ios - Collection View 不滚动之一,容器 View 内