滚动页面以便元素可见

时间:2011-01-11 11:33:52

标签: javascript prototypejs

我刚刚尝试了原型的scrollTo函数,正如文档所述,

  

滚动窗口以便元素   出现在视口的顶部

我想要一个

的功能
    如果元素在视口中不完全可见,则
  1. 仅滚动
  2. 滚动以使元素显示在视口的中心
  3. 有没有人知道原型,scriptaculous或独立的这种功能?

3 个答案:

答案 0 :(得分:6)

我猜您需要这样的demo

<强> window.height

function getWindowHeight() {
  var body  = document.body;
  var docEl = document.documentElement;
  return window.innerHeight || 
         (docEl && docEl.clientHeight) ||
         (body  && body.clientHeight)  || 
         0;
}

<强>滚动

function scrollElemToCenter(id, duration) {
  var el = document.getElementById(id);
  var winHeight = getWindowHeight();
  var offsetTop = el.offsetTop;
  if (offsetTop > winHeight) { 
    var y = offsetTop - (winHeight-el.offsetHeight)/2;
    // wo animation: scrollTo(0, y);
    scrollToAnim(y, duration);
  }
}

动画 (可选,您可以使用script.aculo.us等)

function interpolate(source,target,pos) { return (source+(target-source)*pos); }
function easing(pos) { return (-Math.cos(pos*Math.PI)/2) + 0.5; }

function scrollToAnim(targetTop, duration) {
  duration || (duration = 1000);
  var start    = +new Date,
      finish   = start + duration,
      startTop = getScrollRoot().scrollTop,
      interval = setInterval(function(){
        var now = +new Date, 
            pos = (now>finish) ? 1 : (now-start)/duration;
        var y = interpolate(startTop, targetTop, easing(pos)) >> 0;
        window.scrollTo(0, y);
        if(now > finish) { 
          clearInterval(interval);
        }
      }, 10);
}  

获取滚动根

var getScrollRoot = (function() {
  var SCROLL_ROOT;
  return function() {
    if (!SCROLL_ROOT) {
      var bodyScrollTop  = document.body.scrollTop;
      var docElScrollTop = document.documentElement.scrollTop;
      window.scrollBy(0, 1);
      if (document.body.scrollTop != bodyScrollTop)
        (SCROLL_ROOT = document.body);
      else 
        (SCROLL_ROOT = document.documentElement);
      window.scrollBy(0, -1);
    }
    return SCROLL_ROOT;
  };
})();

答案 1 :(得分:2)

这是一种替代方法,它使用Prototype的一些内置功能来处理视口和滚动尺寸......

function scrollToCenterOfElement(id){
  // Cache element and property lookups...

  var element = $(id);
  var height = element.measure('height');
  var top = element.cumulativeOffset().top;
  var scroll = document.viewport.getScrollOffsets();
  var dimensions = document.viewport.getDimensions();

  // Checks to see if the top offset plus the height of the element is greater
  // than the sum of the viewport height and vertical scroll offset, which means
  // that the element has yet to be fully scrolled in to view, or if the 
  // top offset is smaller than the vertical scroll offset, which means the element
  // has already been (at least partly) scrolled out of view..

  if ((top + height > dimensions.height + scroll.top) || (top < dimensions.height + scroll.top)) {

    // Scroll window to sum of top offset plus half the height of the element
    // minus half of the viewport height, thus centering the element vertically.
    window.scrollTo(0, top + (height / 2) - (dimensions.height / 2));

  }

}

scrollToCenterOfElement('my-element');

答案 2 :(得分:0)

我的解决方案并未涵盖所要求的100%,但也许有人认为它很有用。

/**
 * Scroll container so that given element becomes visible. Features:
 * <ol>
 * <li>If element is already visible, then no action is taken.
 * <li>If element is above view port, the viewport is scrolled upwards so that element becomes visible at the top.
 * <li>If element is below view port, the viewport is scrolled downwards so that element becomes visible at the bottom.
 * </ol>
 *
 * @param element
 *          optional string (selector) or jQuery object that controls the scrolling of the element
 * @param options
 *          optional extra settings
 * @param options.animationSpeed
 *          if defined, then scrolling is animated; determines time in milliseconds after which the element should
 *          be scrolled into viewport
 * @param options.heightScale
 *          double number from 0 to 1; when scrolling the element from bottom sometimes it is desirable to scroll
 *          element close to the top; e.g. to scroll it to the center specify 0.5; to scroll it to the top specify 0
 * @param options.complete
 *          function to be called after animation is completed; if there is no animation, the function is called straight away
 */
$.fn.scrollTo = function(element, options) {
    options = options || {};
    var elementTop = element.offset().top;
    var containerTop = this.offset().top;
    var newScrollTop = null;

    if (elementTop < containerTop) {
        // Scroll to the top:
        newScrollTop = Math.round(this.scrollTop() + elementTop - containerTop);
    } else {
        // Scroll to the bottom:
        var elementBottom = elementTop + element.outerHeight(true);
        var containerHeight = this.height();

        if (elementBottom > containerTop + containerHeight) {
            if (options.heightScale != null) {
                if (options.heightScale === 0) {
                    // This will effectively turn the formulae below into "elementTop - containerTop":
                    containerHeight = element.outerHeight(true);
                } else {
                    containerHeight *= options.heightScale;
                }
            }

            newScrollTop = Math.round(this.scrollTop() + elementBottom - containerTop - containerHeight);
        }
    }

    if (newScrollTop !== null) {
        if (options && options.animationSpeed) {
            this.animate({
                scrollTop : newScrollTop
            }, {
                "duration" : options.animationSpeed,
                "complete" : options.complete
            });
        } else {
            this.scrollTop(newScrollTop);

            if ($.isFunction(options.complete)) {
                options.complete();
            }
        }
    } else {
        if ($.isFunction(options.complete)) {
            options.complete();
        }
    }

    return this;
};

Demo