マウスホイールによるスクロール実装(jQuery)

任意のコンテンツ領域をスクロールさせる場合、デフォルトのスクロールバーではデザイン的に満足できない、もしくはコンテンツ領域が狭くスクロールバーの表示スペースすら消費したくない場合等、マウスホイールによるスクロール実装が行われる事がある。

jQuery TOOLS

jQuery TOOLS
(参考) jQuery tools 日本語リファレンス

シンプルかつパワフルな jQuery plug-in で、最小コーディングでデザイン的にも美しい scrollable 領域を表現することが可能である。また、多くのオプションも用意されておりカスタマイズ性も高い。

問題点

個人的に利用しようとて躓いた点を中心にメモする。
jQuery TOOLSをはじめ、マウスホイールスクロールを実装するライブラリではコンテンツ領域に overflow : hidden をCSSで指定する必要があるらしい。これにより要件を満たさないケースが発生してしまう。例えばコンテンツエリア要素にツールチップを付与した場合等、コンテンツ領域外にはみ出るようなものが隠れて表示出来なくなってしまう。この対処方としては以下の手法が考えられる。

  1. ツールチップをコンテンツ領域と切り離して絶対値のポジションで表示するように修正する
  2. overflow:hidden をやめて独自でスクロールを実装する
  1. の場合、jQuery TOOLS に手を加える、プラス座標計算を的確に行う必要がある。ライブラリのロジックに手を加えるのは基本的にNGだと思うし、座標計算は要素構造が複雑になるに従って正確さが保障できない。という事でこれは無しの方向で。。。
  2. の場合、本来 overflow:hidden させる領域とツールチップ表示域を含む形でさらにDIVとかでwrapして、そのブロックに対して overflow:hidden を適用させる。その上でコンテンツ領域に対して独自にスクロール機能を付与する。これはガッツがいる。

ガッツが要るが、2 を選択する事が最も現実的か。

独自実装

とは言え、マウスホイール周りのライブラリもあるので、それ程でもない。

MOUSE WHEEL EXTENSION

<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="jquery.mousewheel.js"></script>

で、準備して

// 現在のスクロールポジション格納変数(px)
var _curr_top = 0;
// スクロール単位(px)
var _scroll_span = 30;
// コンテンツ領域の全高(px)
var _all_height = $('コンテンツ領域').height() - 0;

// マウスホイールスクロールのイベントハンドリング
$('スクロールを検知する領域').mousewheel(function(_e, _d){

    // 表示領域の高さ
    _vh  = parseInt($('表示領域をwrapする要素').height()) || 0;

    // 下にホイール回す(上方向にスライド)
    if ( _d < 0 ) {
        // コンテンツ全高が表示領域以下の場合は終了
        if ( _all_height < _vh ) return;
        // 終端目標top
        _trgt_top = _curr_top - _scroll_span;
        // マイナスのtop絶対値が(コンテンツ全高-表示域高)より大きくなった場合は(コンテンツ全高-表示域高)に丸める
        _trgt_top = ( Math.abs(_trgt_top) > (_all_height-_vh) ) ? -1*(_all_height-_vh) : _trgt_top;

    // 上にホイール回す(下方向にスライド)
    } else {
        // top 0px の時は終了
        if ( _curr_top == 0 ) return;
        // 終端目標top
        _trgt_top = _curr_top - 0 + _scroll_span;
        // 0を超えてしまう場合は0にする
        _trgt_top = ( _trgt_top > 0 ) ? 0 : _trgt_top;
    }

    // 現在のスクロールtop格納
    _curr_top = _trgt_top;
    // CSS変更
    $('コンテンツ領域').css( {top:_trgt_top+'px'} );
});

こんな感じかなあ。

というか、ツールチップを使わないように設計変更するのが一番なのかもしれない。