javascript - 如何在不闪烁的情况下缩放+滚动JavaScript

标签 javascript html css

我有一个具有缩放功能的 Web 应用程序,它可以缩放一些绝对定位的 DIV 并保持当前的滚动位置。缩放是动画的,问题是明显的滚动位置似乎在动画期间上下闪烁。换句话说,这些盒子看起来就像在播放动画时上下跳跃几个像素。如果可能的话,我希望它更流畅。

问题可以看这里:http://codepen.io/excelkobayashi/pen/EKVmrK .向下滚动到底部并使用 +/- 按钮。向下滚动越远,闪烁越严重。在实际应用中闪烁更明显,可能是因为 DOM 更复杂。

特别注意顶部边缘和文字:

http://i.imgur.com/fbkx1nJ.gifv

下面是滚动的相关代码:

    var oldZoom = zoom;
    zoom += step;

    render();

    scrollPos = ((zoom / oldZoom) * scrollPos) || 0;
    $("#container").scrollTop(scrollPos);

一些注意事项:

  • 这整个 block 是从 requestAnimationFrame 循环中调用的,以动画缩放级别的变化
  • step 是当前缩放和目标缩放之间差异的一小部分,以创建缓出效果。
  • 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 map 等服务通过缩放上一张图像,然后隐藏它并在其后面显示下一张加载的图像来处理此问题。在这种情况下,这似乎不是一个选项,因为这不是基于图像的。

最佳答案

它闪烁是因为你用某个步骤设置了容器的scrollTop值。如果您想逐渐更改 scrollTop,您可能需要查看 jQuery 的 .animate() 函数 (http://api.jquery.com/animate/)。

关于javascript - 如何在不闪烁的情况下缩放+滚动JavaScript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35800615/

相关文章:

html - Bootstrap 文本区域下的未对齐标签

jquery - 无法从 IE8 的下拉列表中选择列表

html - 溢出:在我的响应式菜单上滚动不起作用。该怎么办?

html - 有没有办法在不使用 z-index 的情况下阻止我的图像与标题/导航栏重叠(这似乎不起作用?)

HTML 表单元素未正确对齐

javascript - 如何在nodejs应用程序上定义yield函数

javascript - ReactTable v7 - noDataText 未显示在空数据上(使用 useTableHook)

javascript - NodeJS - Steam API - 自动接受好友请求

javascript - 动态设置DIV的高度

javascript - 将 clearTimeout 与多个 setTimeout 实例一起使用