ブロック要素の中で滑らかスクロールする方法(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]
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]
コード:
javascript:
var SmoothScroll = {};
SmoothScroll = {
targetScrollTop : 0, // we're gonna make the $(parentid).scrollTop -> targetScrollTop
dist : 0,
timer : 0,
count : 0,
parentid : 0,
lastDist : 0,
//speedStore : [], // for debug
options : {},
defaultOptions : {
time : 1*1000, // [ms]
unit : 50 // [ms]
},
scrollTo : function( element, parent, options ){
this.options.time = this.defaultOptions.time;
this.options.unit = this.defaultOptions.unit;
if( options ){
this.options.time = ( options.time ) ? options.time : this.options.time;
this.options.unit = ( options.unit ) ? options.unit : this.options.unit;
}
clearInterval( this.timer );
this.parentid = parent;
this.scrollTopMax = this.$(parent).scrollHeight - this.$(parent).offsetHeight + parseInt(this.$(parent).style.borderTopWidth) + parseInt(this.$(parent).style.borderBottomWidth);
if( navigator.userAgent.match( "MSIE" ) ){
this.targetScrollTop = ( element ) ? this.$(element).offsetTop : 0;
}else{
var targetOffsetTop = ( element ) ? this.$(element).offsetTop : this.$(parent).offsetTop;
this.targetScrollTop = targetOffsetTop - this.$(parent).offsetTop;
}
this.targetScrollTop = ( this.targetScrollTop > this.scrollTopMax ) ? this.scrollTopMax : this.targetScrollTop;
this.dist = this.targetScrollTop - this.$(parent).scrollTop;
this.lastDist = 0;
this.timer = setInterval('SmoothScroll.update()', this.options.unit );
this.count = 0;
//this.speedStore = [];
this.update();
},
update : function(){
var dist = this.targetScrollTop - this.$(this.parentid).scrollTop;
var speed = 2 * dist * this.options.unit / ( this.options.time - this.options.unit * this.count );
//this.speedStore.push( speed );
speed = ( speed > 0 ) ? Math.ceil( speed ) : Math.floor( speed );
if( Math.abs(dist) <= Math.abs(speed) ){
// got there
clearInterval( this.timer );
this.$(this.parentid).scrollTop = this.targetScrollTop;
return;
}else if( this.lastDist == dist ){
// stuck
clearInterval( this.timer );
this.$(this.parentid).scrollTop = this.targetScrollTop;
return;
}
var scrollTop = this.$(this.parentid).scrollTop + speed;
this.$(this.parentid).scrollTop = scrollTop;
this.lastDist = dist;
this.count++;
if( this.count == this.options.time / this.options.unit ){
// timeout
clearInterval( this.timer );
this.$(this.parentid).scrollTop = this.targetScrollTop;
}
},
$ : function(id) {
return document.getElementById(id);
}
}
function gototop(){
document.getElementById('scroll20060827').scrollTop = 0;
}
html:
<div id="scroll20060827" style="width: 100px; height: 100px; overflow-y: scroll; border: 2px black dotted;">
a<br />b<br />c<br />d<br />e<br />f<br />g<br />h<br />
<span id="t20060827i" style="color: red"><b>[i]</b><br />
</span>j<br />k<br />l<br />m<br />n<br />o<br />p<br />q<br />r<br />s<br />t<br />u<br />v<br />w<br />x<br />y<br /><span id="t20060827z" style="color: blue"><b>[z]</b></span><br />
</div>
<input type="button" value="go to top (normal)" onclick="gototop();"/>
<input type="button" value="go to top smoothly" onclick="SmoothScroll.scrollTo(0,'scroll20060827');"/>
<input type="button" value="go to [i] smoothly" onclick="SmoothScroll.scrollTo('t20060827i','scroll20060827');"/>
<input type="button" value="go to [z] smoothly" onclick="SmoothScroll.scrollTo('t20060827z','scroll20060827');"/>
<input type="button" value="go to [i] smoothly, but FAST" onclick="SmoothScroll.scrollTo('t20060827i','scroll20060827',{time: 500});"/>
<input type="button" value="go to [z] smoothly, but FAST" onclick="SmoothScroll.scrollTo('t20060827z','scroll20060827',{time: 500});"/>
<input type="button" value="go to [i] smoothly, but SLOW" onclick="SmoothScroll.scrollTo('t20060827i','scroll20060827',{time: 2000});"/>
<input type="button" value="go to [z] smoothly, but SLOW" onclick="SmoothScroll.scrollTo('t20060827z','scroll20060827',{time: 2000});"/>
