窗口大小调整会导致使用requestAnimationFrame的滚动动画上的元素错位

问题描述 投票:0回答:1

我正在使用jquery.parallax-scroll.js(J.P-S),它依赖于window.requestAnimationFrame来进行滚动动画。我的脚本动画显示元素在x和y轴上的移动,同时滚动以到达并重叠位于页面下方某处的目标元素。

只要窗口没有调整大小,它就能很好地工作。调整窗口大小时,两个元素的位置都会改变,但是已经存在的动画的坐标不会改变,这会导致移动元素在滚动到目标时不再与目标重叠(未对齐)。调整大小后刷新页面可以纠正错位,但出于明显的原因,这不是一个可接受的解决方案。

使用$(window).on('resize',handler),我能够 - 调整大小 - 来更新DOM中动画元素的“data-parallax”属性。这些是为J.P-S提供起始和终止坐标以及行进距离的控制属性。但是,我无法使用更新的坐标重新启动动画。当文件准备好时,确实装载了J.P-S。我的想法是,如果我在使用resize事件的窗口更新“data-”属性后重新启动JP-S脚本,将使用新的更新坐标呈现新动画,并且将更正未对齐...可能是也可能不是正确的方法,但我的想法已经用完...... JP-S有一个非常有限的API,除了初始调用之外没有事件挂钩...

https://codepen.io/decam/pen/daKeyj是一个最小,完整和可验证的例子。请参阅以下片段。

jquery.parallax-scroll.js位于https://github.com/alumbo/jquery.parallax-scroll

如何在不重新加载页面的情况下纠正窗口大小调整导致的错位?

'use strict';

$(function() {
  ScrollAnimations.init();
});

let ScrollAnimations = {
  init: function() {
    this.setAnimations();
  },

  setAnimations: function() {
    setDataPararllax();

    function setDataPararllax() {
      // Get the bullet element's top and left
      // coordinates from declared CSS
      let $bullet = $('#bullet');
      let bullet_top = parseFloat($bullet.css('top'));
      let bullet_left = parseFloat($bullet.css('left'));

      // Get the target element's relative top and
      // left coordinates
      let $target = $('#target');
      let target_top = $target.position().top;
      let target_left = $target.position().left;

      // Calculate x and y distance offsets
      let x_distance = target_left - bullet_left;
      let y_distance = target_top - bullet_top;

      // Prepare JSON objects with the controlling parameters
      // required by the jquery-Parallax-Scrolling.js script
      // to be added as data- attributes of the bullet element
      let data_consts = `"from-scroll": ${bullet_top}, "to-scroll": ${target_top - bullet_top}, "smoothness": 10`;
      let data_p_y = `{"y": ${y_distance}, ${data_consts}}`;
      let data_p_x = `{"x": ${x_distance}, ${data_consts}}`;

      // Add the data- attributes to the bullet element
      $bullet.attr({
        'data-parallax': data_p_y,
        'data-parallax2': data_p_x
      });
    }
  }
};
html,
body,
.panel {
  padding: 0;
  margin: 0;
  color: #96b38a;
  font-family: sans-serif;
  font-size: 20px;
  font-weight: 400;
}


/* Set bullet absolute position to any
  value using top and left properties */

#bullet {
  position: absolute;
  top: 50vh;
  left: 75vw;
}

#top {
  height: 120vh;
  background-color: #333333;
  text-align: center;
}

#bottom {
  height: 250vh;
  background-color: #666666;
}

.panel {
  display: flex;
  align-items: center;
  justify-content: center;
}

span {
  font-size: 2em;
  color: #ddca7e;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1" />
  <title>Scroll Bullet->Target Animation</title>
</head>

<body>
  <svg id="bullet" height="10" width="10">
      <circle cx="5" cy="5" r="5" fill="white" />
    </svg>
  <div id="top" class="panel">
    <p><span>Scroll down...</span><br> Window resizing is NOT yet supported...<br> If white bullet doesn't overlap the black target after scrolling,<br>you've resized the window...<br> Refresh the browser and try again.<br> I'm currently working on a solution...
    </p>
  </div>
  <div id="bottom" class="panel">
    <svg id="target" height="10" width="10">
        <rect width="10" height="10" fill="black" />
      </svg>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
  <script src="https://cdn.jsdelivr.net/gh/alumbo/jquery.parallax-scroll/js/jquery.parallax-scroll.js"></script>
</body>

</html>
jquery scroll jquery-plugins window-resize requestanimationframe
1个回答
0
投票

我找到了一个解决方案,我正在回答我自己的问题,以防其他人在将来碰到类似的事情。

J.P-S脚本通过基于通过data-parallax属性传递的JSON设置来动画化DOM元素的样式来工作。该脚本将样式属性添加到动画中。

为了在调整窗口大小时重新调整元素(及其动画),我在windows resize事件上调用一个函数来替换data-parallax属性。我从DOM元素中删除了整个data-parallax和style属性,而不仅仅是它们的值,并使用其他名称和新值附加新数据属性。使用计数器,我创建并附加新的数据属性。例如。第一次调整大小事件的data-1parallax,第二次调整大小的data-2parallax,依此类推。然后我调用我添加到J.P-S脚本中的一个小函数,该函数替换脚本用于获取参数和动画元素的数据属性名称。该名称将替换为在resizing事件上生成的匹配名称(我传递计数器值);显然,我已经在脚本中将数据属性名称变为变量。

因此,我最终获得了新数据 - [#]视差属性,其中调整大小后的JSON值(先前数据 - [#]视差属性被删除),然后脚本生成具有正确值的新样式属性。对事件进行辩解可确保每次调整窗口大小时,我只运行一次此过程。如果有人需要更多澄清或代码,请发表评论,我会提供。

我已经使用更正版本更新了CodePen,您可以在那里演示可调整大小的脚本。请参阅问题中的CodePen链接。

© www.soinside.com 2019 - 2024. All rights reserved.