ブロック要素の中で滑らかスクロールする方法(javascript)2

Posted on 8月 27, 2006
Filed Under javascript |

昨日の ブロック要素の中で滑らかスクロールする方法(javascript) はつくってて楽しかった♪
Flashアプリとかつくる人にとっては当たり前な気がしますが。

usage:
http://slightlyblue.com/lab/t20060827/smoothscroll.js を読み込んで、
SmoothScroll.scrollTo( ‘target id’, ‘parent id’, options);
‘parent id’ はスクロールしようとしているブロック要素のid
‘target id’ は ‘parent id’ブロック内にあるスクロール目標(=スクロール後にブロックの一番上に表示させたい行)のid
options は { time : 500, unit : 50 } 等と指定する
options.time は スクロール完了までの時間
options.unit は スクロール完了までに何ms単位で細かくスクロールするか
映画のフレームレート:24fps(40ms/frame)が映像を滑らかに見せるぎりぎりのラインだと思うので、それくらいを目安に。

point1:
滑らかなスクロールは、
$(’parent id’).scrollTop を options.unit 毎に更新することで実現します。
更新毎の移動量は、線形に漸減する方式になっています。

目標の距離に対して、options.time / options.unit 回に分けてスクロールするので、
目標の距離 / ( options.time / options.unit ) だけ一度に動かすと、速度変化は起きません。

線形に漸減させるためには、
一回の移動量 = 目標の距離 / ( options.time / options.unit ) * 2
x2すればいいのです。
この三角形を意識すれば簡単。

4分の1円形状に速度が落ちていったらかっこいいかな、なんて考えたりすると楽しい。。

point2:
もうひとつのポイントは、IE/Firefoxの違い
MSDN Home > 連載コラム > DHTML Dude > 配置と編集
HTML要素のサイズや位置を取得する
この辺りが詳しい。
offsetTopを使って、スクロールの目標を決めているのだけれど、
offsetTopがどこ基準のオフセットなのか、ブラウザ依存。
ここでは、’parent id’のwidth,heightを絶対値指定して、’parent id’ブロックをその内側にある’target id’のoffsetParentにしている。

もし万が一使うことがありそうだったらコメントいただけたらうれしいです。

Comments

Leave a Reply




ブロック要素の中で滑らかスクロールする方法(javascript)

Posted on 8月 27, 2006
Filed Under javascript |

ブロック要素の中で滑らかスクロールする方法(javascript)
IE,Firefoxのみで動作確認(IE追加@2006/08/27)

気持ちいいインターフェース。
Scriptaculous.Effects.ScrollTo をHackする方法もあるけれど、重いので自前で。

明日解説するかも。

a
b
c
d
e
f
g
h
[i]
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
[z]

コード:

CODE:
  1. javascript:
  2. var SmoothScroll = {};
  3. SmoothScroll = {
  4. targetScrollTop : 0,    // we're gonna make the $(parentid).scrollTop -> targetScrollTop
  5. dist : 0,
  6. timer : 0,
  7. count : 0,
  8. parentid : 0,
  9. lastDist : 0,
  10. //speedStore : [],    // for debug
  11. options : {},
  12. defaultOptions : {
  13. time : 1*1000// [ms]
  14. unit : 50         // [ms]
  15. },
  16. scrollTo : function( element, parent, options ){
  17. this.options.time = this.defaultOptions.time;
  18. this.options.unit = this.defaultOptions.unit;
  19. if( options ){
  20. this.options.time = ( options.time ) ? options.time : this.options.time;
  21. this.options.unit = ( options.unit ) ? options.unit : this.options.unit;
  22. }
  23. clearInterval( this.timer );
  24. this.parentid = parent;
  25.  
  26. this.scrollTopMax = this.$(parent).scrollHeight - this.$(parent).offsetHeight + parseInt(this.$(parent).style.borderTopWidth) + parseInt(this.$(parent).style.borderBottomWidth);
  27.  
  28. if( navigator.userAgent.match( "MSIE" ) ){
  29. this.targetScrollTop = ( element ) ? this.$(element).offsetTop : 0;
  30. }else{
  31. var targetOffsetTop = ( element ) ? this.$(element).offsetTop : this.$(parent).offsetTop;
  32. this.targetScrollTop = targetOffsetTop - this.$(parent).offsetTop;
  33. }
  34. this.targetScrollTop = ( this.targetScrollTop> this.scrollTopMax ) ? this.scrollTopMax : this.targetScrollTop;
  35.  
  36. this.dist = this.targetScrollTop - this.$(parent).scrollTop;
  37. this.lastDist = 0;
  38. this.timer = setInterval('SmoothScroll.update()', this.options.unit );
  39. this.count = 0;
  40. //this.speedStore = [];
  41. this.update();
  42. },
  43. update : function(){
  44. var dist = this.targetScrollTop - this.$(this.parentid).scrollTop;
  45. var speed = 2 * dist * this.options.unit / ( this.options.time - this.options.unit * this.count );
  46. //this.speedStore.push( speed );
  47. speed = ( speed> 0 ) ? Math.ceil( speed ) : Math.floor( speed );
  48. if( Math.abs(dist) <= Math.abs(speed) ){
  49. // got there
  50. clearInterval( this.timer );
  51. this.$(this.parentid).scrollTop = this.targetScrollTop;
  52. return;
  53. }else if( this.lastDist == dist ){
  54. // stuck
  55. clearInterval( this.timer );
  56. this.$(this.parentid).scrollTop = this.targetScrollTop;
  57. return;
  58. }
  59. var scrollTop = this.$(this.parentid).scrollTop + speed;
  60. this.$(this.parentid).scrollTop = scrollTop;
  61. this.lastDist = dist;
  62. this.count++;
  63. if( this.count == this.options.time / this.options.unit ){
  64. // timeout
  65. clearInterval( this.timer );
  66. this.$(this.parentid).scrollTop = this.targetScrollTop;
  67. }
  68. },
  69. $ : function(id) {
  70. return document.getElementById(id);
  71. }
  72. }
  73. function gototop(){
  74. document.getElementById('scroll20060827').scrollTop = 0;
  75. }
  76.  
  77. html:
  78.  
  79. </p><p id="scroll20060827" style="border: 2px dotted black; width: 100px; height: 100px; overflow-y: scroll"> a
  80. b
  81. c
  82. d
  83. e
  84. f
  85. g
  86. h
  87. <span id="t20060827i" style="color: red"><strong>[i]</strong>
  88. </span>j
  89. k
  90. l
  91. m
  92. n
  93. o
  94. p
  95. q
  96. r
  97. s
  98. t
  99. u
  100. v
  101. w
  102. x
  103. y
  104. <span id="t20060827z" style="color: blue"><strong>[z]</strong></span> <input value="go to top (normal)" onclick="gototop();" type="button" /> <input value="go to top smoothly" onclick="SmoothScroll.scrollTo(0,'scroll20060827');" type="button" /> <input value="go to [i] smoothly" onclick="SmoothScroll.scrollTo('t20060827i','scroll20060827');" type="button" /> <input value="go to [z] smoothly" onclick="SmoothScroll.scrollTo('t20060827z','scroll20060827');" type="button" /> <input value="go to [i] smoothly, but FAST" onclick="SmoothScroll.scrollTo('t20060827i','scroll20060827',{time: 500});" type="button" /> <input value="go to [z] smoothly, but FAST" onclick="SmoothScroll.scrollTo('t20060827z','scroll20060827',{time: 500});" type="button" /> <input value="go to [i] smoothly, but SLOW" onclick="SmoothScroll.scrollTo('t20060827i','scroll20060827',{time: 2000});" type="button" /> <input value="go to [z] smoothly, but SLOW" onclick="SmoothScroll.scrollTo('t20060827z','scroll20060827',{time: 2000});" type="button" />

Comments

One Response to “ブロック要素の中で滑らかスクロールする方法(javascript)”

  1. blog@slightlyblue on 8月 27th, 2006 19:57

    ブロック要素の中で滑らかスクロールする方法(javascript)2

    昨日の ブロック要素の中で滑らかスクロールする方法(javascript) は…

Leave a Reply