【问题标题】:scrollintoview animation滚动查看动画
【发布时间】:2012-08-19 14:06:50
【问题描述】:

我的代码是http://jsfiddle.net/mannagod/QT3v5/7/

JS 是:

function delay() {
    var INTENDED_MONTH = 7 //August
    // INTENDED_MONTH is zero-relative
    now = new Date().getDate(),
rows = document.getElementById('scripture').rows;
    if (new Date().getMonth() != INTENDED_MONTH) {
        // need a value here less than 1, 
        // or the box for the first of the month will be in Red
        now = 0.5
    };
    for (var i = 0, rl = rows.length; i < rl; i++) {
        var cells = rows[i].childNodes;
        for (j = 0, cl = cells.length; j < cl; j++) {
            if (cells[j].nodeName == 'TD'
  && cells[j].firstChild.nodeValue != ''
  && cells[j].firstChild.nodeValue == now) {
                // 'ffff99' // '#ffd700' // TODAY - red
                rows[i].style.backgroundColor = 'red' 
                rows[i].scrollIntoView();
            }
        }
    }
}

我需要找到一种方法来平滑.scrollintoview()。现在它“跳转”到突出显示的行。我需要它顺利过渡到该行。它需要动态完成以替换scrollintoview。有任何想法吗?谢谢。

【问题讨论】:

    标签: scroll smooth js-scrollintoview


    【解决方案1】:

    在大多数现代浏览器 (Chrome and Firefox, but not Safari, UC, or IE) 中,您可以将对象中的选项传递给 .scrollIntoView()

    试试这个:

    elm.scrollIntoView({ behavior: 'smooth', block: 'center' })
    

    其他值为behavior: 'instant'block: 'start'block: 'end'。见https://developer.mozilla.org/en/docs/Web/API/Element/scrollIntoView

    【讨论】:

    • 呵呵,Firefox 比 Chrome 做得更好的一件事
    • 现在它适用于所有主要浏览器。唯一的兼容性问题是不完全兼容的平滑行为:caniuse.com/#feat=scrollintoview
    • 使用 polyfill 使 scrollintoviewoptions 浏览器独立,你就完成了 :) stackoverflow.com/questions/42503599/…
    • 建议第一行代码必须是 >>> var elmnt = document.getElementById("content");
    【解决方案2】:

    我也在搜索这个问题并找到了这个解决方案:

    $('html, body').animate({
        scrollTop: $("#elementId").offset().top
    }, 1000);
    

    资源: http://www.abeautifulsite.net/smoothly-scroll-to-an-element-without-a-jquery-plugin-2/

    【讨论】:

    • 这是最好的答案。它平滑地滚动到所需的位置。谢了!
    【解决方案3】:

    也许你不想仅仅为了实现这个特性而添加 jQuery。 elem 是要滚动的元素。目标位置可以从要移动到视图中的元素的 offsetTop 属性中获取。

    function Scroll_To(elem, pos)
    {
        var y = elem.scrollTop;
        y += (pos - y) * 0.3;
        if (Math.abs(y-pos) < 2)
        {
            elem.scrollTop = pos;
            return;
        }
        elem.scrollTop = y;
        setTimeout(Scroll_To, 40, elem, pos);   
    }
    

    【讨论】:

    • 我遇到了无限递归的问题。我用Math.round( ( pos - y ) * 0.3 );Math.abs(y-pos) &lt;= 2 修复了它
    【解决方案4】:

    在没有 jQuery 的情况下使用 requestAnimationFrame 在特定持续时间内平滑滚动。

    演示:http://codepen.io/Shadeness/pen/XXyvKG?editors=0010

    window.bringIntoView_started = 0;
    window.bringIntoView_ends = 0;
    window.bringIntoView_y = 0;
    window.bringIntoView_tick = function() {
      var distanceLeft, dt, duration, t, travel;
      t = Date.now();
      if (t < window.bringIntoView_ends) {
        dt = t - window.bringIntoView_started;
        duration = window.bringIntoView_ends - window.bringIntoView_started;
        distanceLeft = window.bringIntoView_y - document.body.scrollTop;
          travel = distanceLeft * (dt / duration);
          document.body.scrollTop += travel;
          window.requestAnimationFrame(window.bringIntoView_tick);
      } else {
        document.body.scrollTop = window.bringIntoView_y;
      }
    };
    window.bringIntoView = function(e, duration) {
      window.bringIntoView_started = Date.now();
      window.bringIntoView_ends = window.bringIntoView_started + duration;
      window.bringIntoView_y = Math.min(document.body.scrollTop + e.getBoundingClientRect().top, document.body.scrollHeight - window.innerHeight);
      window.requestAnimationFrame(window.bringIntoView_tick);
    };
    

    例如:

    bringIntoView(document.querySelector('#bottom'), 400)
    

    它应该随着dt (deltaTime) 变大而加速,并随着distanceLeft 变小而减慢。如果用户滚动但我考虑打破循环。全局变量会阻止之前的调用完全接管,但不会取消之前的递归循环,因此它的动画速度会提高一倍。

    【讨论】:

    • 奇数。看起来您需要使用window.scrollTo(x, 0) 而不是分配给.scrollTopHere's another answer 在 StackOverflow 上。
    【解决方案5】:

    你只需要包含这个 polyfill 就可以了。

    https://github.com/iamdustan/smoothscroll

    <script src="js/smoothscroll.js"></script>
    

    如果您使用 npm,则需要它。

    require('smoothscroll-polyfill').polyfill();
    

    使用原生 scrollIntoView 方法。

    document.getElementById('parallax-group-logo').scrollIntoView({
        block: "start",
        behavior: "smooth"
    });
    

    【讨论】:

      【解决方案6】:

      试试这个:

      function scroll_into_view_smooth(elem)
      {   var FPS = 48; // frames per second
          var DURATION = 0.6; // sec
          var e = elem;
          var left = e.offsetLeft;
          var top = e.offsetTop;
          var width = e.offsetWidth;
          var height = e.offsetHeight;
          var body = document.body;
          var to_scroll = [];
          var p, offset;
          while ((p = e.offsetParent))
          {   var client_width = p.clientWidth;
              var client_height = p!=body ? p.clientHeight : Math.min(document.documentElement.clientHeight, window.innerHeight);
              if (client_width<p.scrollWidth-1 && ((offset=left-p.scrollLeft)<0 || (offset=left+width-p.scrollLeft-client_width)>0))
              {   to_scroll.push({elem: p, prop: 'scrollLeft', from: p.scrollLeft, offset: offset});
              }
              if (client_height<p.scrollHeight-1 && ((offset=top-p.scrollTop)<0 || (offset=top+height-p.scrollTop-client_height)>0))
              {   to_scroll.push({elem: p, prop: 'scrollTop', from: p.scrollTop, offset: offset});
              }
              e = p;
              left += e.offsetLeft;
              top += e.offsetTop;
          }
          var x = 0;
          function apply()
          {   x = Math.min(x+1/(DURATION * FPS), 1);
              for (var i=to_scroll.length-1; i>=0; i--)
              {   to_scroll[i].elem[to_scroll[i].prop] = to_scroll[i].from + to_scroll[i].offset*x*x;
              }
              if (x < 1)
              {   setTimeout(apply, 1000/FPS);
              }
          }
          apply();
      }
      

      【讨论】:

        【解决方案7】:

        只是添加到这里以防它帮助某人,

        我正在为 iOS 和 Android 开发 PWA,并使用 scrollIntoView() 方法,直到我发现 Safari 不支持 scrollIntoViewOptions 对象,因此无法平滑滚动或其他任何东西。

        对于带有普通 JS 的 iOS,我能够模仿 scrollIntoView 的功能,具有平滑滚动和“最近”选项……嗯,普通 TypeScript……

        点击处理程序或 w/e:

        const element = *elementToScrollIntoView*;
        const scrollLayer = *layerToDoTheScrolling*
        
        if (/iPad|iPhone|iPod/.test(navigator.userAgent) {
            let position;
            const top = element.offsetTop - scrollLayer.scrollTop;
            if (element.offsetTop < scrollLayer.scrollTop) {
                    // top of element is above top of view - scroll to top of element
                position = element.offsetTop;
            } else if (element.scrollHeight + top < scrollLayer.offsetHeight) {
                    // element is in view - don't need to scroll
                return;
            } else if (element.scrollHeight > scrollLayer.offsetHeight) {
                    // element is bigger than view - scroll to top of element
                position = element.offsetTop;
            } else {
                    // element partially cut-off - scroll remainder into view
                const difference = scrollLayer.offsetHeight - (element.scrollHeight + top);
                position = scrollLayer.scrollTop - difference;
            }
                // custom function for iOS
            scrollToElement(scrollLayer, position, 200);
        } else {
                // just use native function for Android
            element.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
        }
        

        手动滚动功能:

        scrollToElement(scrollLayer, destination, duration) {
            if (duration <= 0) {
                return;
            }
            const difference = destination - scrollLayer.scrollTop;
            const perTick = (difference / duration) * 10;
        
            setTimeout(() => {
                scrollLayer.scrollTop = scrollLayer.scrollTop + perTick;
                if (scrollLayer.scrollTop === destination) {
                    return;
                }
                scrollToElement(scrollLayer, destination, duration - 10);
            }, 10);
        }
        

        注意: 处理程序中的大嵌套 if 和计算只是为了找到“最近”位置,因为我试图复制该行为,但只是使用 scrollToElement 函数动画滚动到顶部(没有选项对象的默认行为)您可以使用:

        scrollToElement(scrollLayer, element.offsetTop, 200);
        

        【讨论】:

          【解决方案8】:

          您可以尝试将 evt.preventDefault() 添加到函数中。这应该会覆盖正常的“点击链接”功能。示例:

              // Scroll to anchor ID using scrollTO event
          function linkClicked(evt) { // function to listen for when a link is clicked
            evt.preventDefault();
            evt.scrollIntoView({behavior: 'smooth'});
          
          }
          
          // Scroll to section on link click
          navBar.addEventListener('click', linkClicked);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-03-01
            • 2011-06-28
            • 1970-01-01
            • 1970-01-01
            • 2015-03-17
            • 1970-01-01
            • 2019-07-22
            相关资源
            最近更新 更多