【发布时间】:2016-03-04 16:05:45
【问题描述】:
我有一个带有缩放功能的 Web 应用程序,它可以缩放一些绝对定位的 DIV 并保持当前滚动位置。缩放是动画的,问题是明显的滚动位置在动画过程中似乎上下闪烁。换句话说,当动画播放时,盒子看起来像是上下跳跃了几个像素。如果可能的话,我希望它更流畅。
问题可以在这里看到:http://codepen.io/excelkobayashi/pen/EKVmrK。向下滚动到底部并使用 +/- 按钮。滚动得越远,闪烁越严重。在实际应用中闪烁更明显,可能是因为 DOM 更复杂。
特别注意顶部边缘和文字:
这里是滚动的相关代码:
var oldZoom = zoom;
zoom += step;
render();
scrollPos = ((zoom / oldZoom) * scrollPos) || 0;
$("#container").scrollTop(scrollPos);
一些注意事项:
- 从 requestAnimationFrame 循环调用整个块以动画化缩放级别的变化
- 步长是当前缩放和目标缩放之间差异的一小部分,用于创建缓出效果。
- render 是在可滚动区域内调整和移动 DIV 大小的函数
var zoom = 1;
var targetZoom = 1;
var lastTick = null;
var scrollPos = 0;
function render() {
$(".main").height(1000 * zoom).each(function() {
var pos = 10 * zoom;
var height = 30 * zoom;
$(this).find(".stuff").each(function() {
$(this).css("top", pos + "px");
$(this).css("height", height + "px");
pos += 50 * zoom;
});
})
}
function animate() {
var diff = targetZoom - zoom;
if (!diff) {
lastTick = null;
return;
}
var tick = new Date().getTime();
if (lastTick) {
var minDiff = 0.01;
var timeDiff = tick - lastTick;
var step = diff * timeDiff / 100;
if (diff > 0 && step <= minDiff)
step = Math.min(minDiff, diff);
else if (diff < 0 && step >= -minDiff)
step = Math.max(-minDiff, diff);
var oldZoom = zoom;
zoom += step;
render();
scrollPos = ((zoom / oldZoom) * scrollPos) || 0;
$("#container").scrollTop(scrollPos);
}
lastTick = tick;
requestAnimationFrame(animate);
}
function startAnimation() {
if (lastTick)
return;
animate();
}
$("#zoomIn").click(function() {
targetZoom += 0.2;
startAnimation();
})
$("#zoomOut").click(function() {
targetZoom -= 0.2;
startAnimation();
})
$("#container").scroll(function() {
var scrollTop = $(this).scrollTop();
var diff = scrollPos - scrollTop;
if (isNaN(diff) || diff < 0 || diff >= 1)
scrollPos = scrollTop;
})
render();
div {
border: 1px solid black;
box-sizing: border-box;
}
#container {
margin: 10px;
width: 1200px;
height: 400px;
overflow: auto;
display: flex;
flex-direction: row;
}
.main {
width: 200px;
overflow: hidden;
position: relative;
/* Slow rendering (simulate complex content) */
box-shadow: 5px 5px 10px #888;
background-image: linear-gradient(to right, #fdd, #ddf);
}
.stuff {
position: absolute;
left: 10px;
right: 10px;
overflow: hidden;
/* Slow rendering (simulate complex content) */
box-shadow: 5px 5px 10px #888;
background-image: linear-gradient(white, #aaa);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="zoomOut">-</button>
<button id="zoomIn">+</button>
<div id="container">
<div class="main">
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
</div>
<div class="main">
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
</div>
<div class="main">
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
</div>
<div class="main">
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
</div>
<div class="main">
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
</div>
<div class="main">
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
<div class="stuff">Stuff</div>
</div>
</div>
关于我研究过的事情的一些注释:
- 浏览器对 scrollTop 值进行四舍五入。
- 应该考虑到这一点,因为我有一个单独的变量来存储预期的位置,但这种舍入可能仍然是罪魁祸首。
- 在调用 scrollTop 之前添加圆形/地板似乎没有效果。
- 不能使用 CSS 转换,因为我不希望它影响内部 DIV 的内容;放大应该会显示更多内容。
- 调换调用 render 和 scrollTop 的顺序不会改变任何东西。
- 设置 scrollTop 会导致重绘,但据我所知调用 render 不应该。
- Google Maps 等服务通过缩放前一个图像、然后隐藏它并在其后面显示下一个加载的图像来处理此问题。在这种情况下,这似乎不是一个选项,因为这不是基于图像的。
【问题讨论】:
标签: javascript html css