スクロールに連動して、要素を動かす。(書き直し)

ページの途中などで戻りたいときに「戻る」アンカーでも配置する。
エレベーターは、右下に寄り添う。
スクロールがトップの位置にくると消える。

  • -

ことあるごとに、スクロールイベント処理を追加すのは、イケてない。

(function () { //@cc_on

  // This Object !!
  function Elevator (arg) {
    this.body     = arg.body;      // document.documentElement or body
    this.node     = arg.node;      // target node
    this.accell   = arg.accell;    // acceleration (1 < accell)
    this.interval = arg.interval;  // timer interval
    this.offset   = arg.offset;    // target offset position 
    this.timerId  = null;          // timer
    this.x        = arg.x;
    this.y        = arg.y;
  }
  
//______________________________________________________________________

  // 透明度の設定
  function Decorator (alpha) {
    if (alpha < 0)
      return this.visibility = 'hidden';
    
    if (100 < alpha)
      alpha = 100;
    
    this.visibility = 'visible';
     
    this/*@if (@_jscript)
      .filter = 'Alpha(opacity=' + alpha + ')' @else@*/
      .opacity = String (alpha / 100) /*@end@*/;
  }

  
  // 位置の設定
  function Locator (x, y) {
    this.top = y + 'px';
    this.left = x + 'px';
  }
  

  // スタート処理
  function Elevator_start () {
    if (! this.timerId) {
      var that = this;
      var cbFunc = function () { Elevator_onTimer.call (that) };
      this.timerId = setInterval (cbFunc, this.interval);
    }
  };


  // ストップ処理
  function Elevator_stop () {
    if (this.timerId) {
      clearInterval (this.timerId);
      this.timerId = null;
      Decorator.call (this.style, -1);
    }
  };


  // 移動処理ループ
  function Elevator_onTimer () {
    var e = this.node;
    var b = this.body;
    var v = e.ownerDocument./*@if (@_jscript) parentWindow @else@*/ defaultView /*@end@*/;
    var a = this.accell;
    var o = this.offset;
    var style = e.style;
    
    var pointerX = /*@if (@_jscript) b.scrollLeft @else@*/ v.pageXOffset /*@end@*/;
    var pointerY = /*@if (@_jscript) b.scrollTop  @else@*/ v.pageYOffset /*@end@*/;
    var opY = pointerY;
    
    pointerX += b.clientWidth - e.offsetWidth + o.x;
    pointerY += b.clientHeight - e.offsetHeight + o.y;

    var diffX = (pointerX - this.x) / a;
    var diffY = (pointerY - this.y) / a;
    
    diffX = (diffX < 0) ? Math.floor (diffX) : Math.ceil (diffX);
    diffY = (diffY < 0) ? Math.floor (diffY) : Math.ceil (diffY);
    
    if (0 == diffX)
      if (0 == diffY)
        Elevator_stop.call (this);
    
    this.x += diffX;
    this.y += diffY;

    Decorator.call (style, opY);
    Locator.call (style, this.x , this.y);
  };


  // 初期化&オブジェクト生成
  function Elevator_create (target, accell, interval, offset) {
    if (1 > arguments.length)
      return null;

    offset = offset ||  { x: 0, y: 0 };
    
    var elevator;
    var doc = target.ownerDocument;
    var style = target.style;
    var base = doc[(doc.compatMode == 'CSS1Compat') ? 'documentElement' : 'body'];
    var arg = {
      body     : base,
      node     : target,
      accell   : accell || 2,
      interval : interval || 50,
      x        : base.clientWidth - target.offsetWidth + offset.x,
      y        : base.clientHeight - target.offsetHeight + offset.y,
      offset   : offset
    };

    // スクロールイベントのリスナー
    function onScroll (evt) {
      Elevator_start.call (elevator);
    }


    // 終了処理
    function onUnload (evt) {
      window./*@if (@_jscript) detachEvent ('on' + @else@*/ removeEventListener ( /*@end@*/ 'unload', arguments.callee, false);
      doc./*@if (@_jscript) detachEvent ('on' + @else@*/ removeEventListener ( /*@end@*/ 'scroll', onScroll, false);
      doc = style = arg = elevator = onScroll = onUnload = null;
    }
    
    
    // 初期化イベント処理
    function onload (event) {
      window./*@if (@_jscript) attachEvent ('on' + @else@*/ addEventListener (/*@end@*/ 'unload', onUnload, false);
      doc./*@if (@_jscript) attachEvent ('on' + @else@*/ addEventListener (/*@end@*/ 'scroll', onScroll, false);
    }

    
    // 初期化
    function init () {
      onload ();
      style.position = 'absolute';
      style.margin = '0';
    }

    init ();
    elevator = new Elevator (arg);
    elevator.start ();

    return elevator;
  }


//______________________________________________________________________

  Elevator.create            = Elevator_create;
  
  Elevator.prototype.start   = Elevator_start;
  Elevator.prototype.stop    = Elevator_stop;
  
  this.Elevator = Elevator;
  
})();