情况:
假设我们正在阅读页面中的内容,该内容是为响应而构建的。假设我们还将浏览器窗口的大小调整为较小的尺寸,并且由于宽度较薄,上面的某些内容会向下延伸,从而使整个页面更长。然后,当我们调整大小时,我们正在查看的任何内容都将相应地向下推送到页面。
示例:
假设我们要查看this page中的帮助程序类部分。然后缩小/扩展窗口足够的量会移动我们正在向下/向上读取当前视图的位。
提示:
有什么办法可以解决这个问题吗?即当我们调整窗口大小时,无论其上面的内容发生什么,都要保持我们当前的页面视图。
思想:
我想我们至少可以从javascript开始并在窗口调整大小上放置一个事件。然后自动将页面滚动到事件触发时我们视图中的最顶层元素。但是,我不知道这会对性能产生什么影响,特别是在较大的页面中
还有在当前视图中引用最顶层元素的问题。我们当前视图的顶部可能是切掉某些元素的顶部部分,更不用说在页面内的任何一点上通常有多于1个元素叠加在一起。我提到的最顶层元素的概念定义不明确:(
而且一般而言,不是响应式设计的问题,而是在我看来,这是Web浏览器的默认滚动行为的问题?或者我可能缺少一些需要当前行为的情况。
编辑 2 4
根据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);
即使在相同的浏览器中,小提琴也有点怪异,我使用免费托管here上传了相同的脚本。
仍然需要为elementFromPoint
合并IE,Opera和Safari修复程序。
编辑3
感谢所有帮助,Rick Hitchcock。欢迎来到stackoverflow,顺便说一下:)
讨论正在变成跨浏览器兼容性问题,因此我已经接受了您的回答,因为我们已经得到了原始问题的答案。我仍然会修复我的实现。重点是跨浏览器问题,topNode标准和topNode截止处理。
边缘案例
在玩它时,我注意到当我们在一个小视口中位于页面底部时,然后切换到一个更大的视口(让我们假设现在有些元素最初位于我们现在看到的元素之上由于较宽的视口中的较短容器而进入视野)在这种情况下,窗口不能始终将topNode锁定到视口的顶部,因为我们已经到达滚动底部。但是,切换回小视口现在使用在切换期间进入视口的新topNode 虽然这应该从正在实施的行为中得到预期,但它仍然是滚动底部的奇怪副作用。
我也会在适当的时候研究这个问题。最初,我想在更新topNode之前简单地添加一个滚动底部检查。即当我们达到滚动底部直到我们再次向上滚动时保持旧的topNode。不知道结果如何。我将确保看到Opera如何处理这个问题。
答案 0 :(得分:2)
以下是我提出的建议:
(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);
}
}
)();
}
}
)();
如果有一个窗口。 onbeforeresize()功能,这会更直接。
请注意,这并未考虑元素textNode的滚动位置。如果仅调整窗口的 height ,我们可以处理。但是,调整 width 的大小通常会导致重新格式化。
适用于Chrome,Firefox,IE和Safari。
代码的闭包使变量变为私有,定时器阻止代码在滚动/调整大小期间不断运行。但两者都倾向于混淆代码,所以这是另一个版本,这可能有助于理解。请注意,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 维护屏幕的最顶层元素。
该功能沿着第3行从左到右扫描屏幕:document.elementFromPoint(x,2)
*
它不会沿着第一行扫描,因为当IE执行 scrollIntoView 时,它会将元素向下推几个像素,使得最顶层的屏幕元素 previous < / em>元素。 (通过试验和错误计算出来。)
调整窗口大小时,只需将 topNode 放在屏幕顶部即可。
[*最初, onscroll 沿 11th 行(以像素为单位)从左向右扫描,直到找到只有一个孩子的元素。孩子通常是一个textNode,但情况并非总是如此。例如:
<div><ul><li>...<li>...<li>...</ul></div>
div 只有一个孩子 - ul 。如果窗口滚动到第50个 li ,由于 li 的固有填充,从左到右扫描会错误地返回 div 。< / p>
原始代码已更新。 ]