div要素などをスクロールに追随させるJavaScriptの続きです。
クラス化と、間違いや、効率的でないところの修正もしています。
サンプル(スクリプト以外は前回と同じ)
とりあえず隠蔽する
これでグローバル変数は2つになる。
でも、この場合、ScrollChaser
のプロパティにはアクセスできない。
function ScrollChaser(id,int)
{
var el;
var initTop;
var interval = int;
//
function setting()
{
el = document.getElementById(id);
el.style.position = 'absolute';
initTop = el.offsetTop;
//
try {
window.addEventListener('scroll', scrollEvent, false);
} catch (e) {
window.attachEvent('onscroll',scrollEvent);
}
}
function scrollEvent()
{
var myInt = setInterval(function()
{
var cur = (document.body.scrollTop||document.documentElement.scrollTop)+20;
var myTop = el.offsetTop;
var d = cur-myTop;
if(Math.abs(d) > 1) {
if( cur < = initTop )
{
var y = myTop + d/3;
el.style.top = y+"px";
} else {
el.style.top = initTop+"px";
clearInterval(myInt);
}
} else {
el.style.top = cur+"px";
clearInterval(myInt);
}
},interval);
}
try {
window.addEventListener('load', setting, false);
} catch (e) {
window.attachEvent('onload', setting);
}
}
//
var sc = new ScrollChaser('side',200);
prototypeプロパティを使用する
prototype
プロパティはnew
演算子でオブジェクトが生成されたときに設定されます。
prototype
プロパティに追加されたプロパティはそのオブジェクトの全てのインスタンスで使うことができます。これによりクラス的なオブジェクトの使い方ができるようになります。
prototype
プロパティによりScrollChaser
内のプロパティにアクセスできるようになりました。ただ、注意しないといけないのは、window.onload
やsetInterval()
からプロパティを呼び出すときにスコープを指定しないと呼び先のthis
がオブジェクト本体を参照しなくなる(window
だとグローバルオブジェクトを参照することになるのかな?)ところ。ローカル変数にthis
を格納してローカル変数を参照しなければなりません。
インスタンスプロパティ(this.hogehoge
)にいちいちthisキーワードを指定しないといけないのは面倒いな。上記のようなActionScript的な書き方ができればいいのに。
function ScrollChaser(id,int)
{
this.interval = int;
this.id = id;
}
//
ScrollChaser.prototype.init = function()
{
var scope = this;
//
try {
window.addEventListener('load', scope.setting, false);
} catch (e) {
window.attachEvent('onload', scope.setting);
}
}
ScrollChaser.prototype.setting = function()
{
var scope = this;
//
this.el = document.getElementById(this.id);
this.el.style.position = 'absolute';
this.initTop = this.el.offsetTop;
//
try {
window.addEventListener('scroll', scope.scrollEvent, false);
} catch (e) {
window.attachEvent('onscroll', scope.scrollEvent);
}
}
ScrollChaser.prototype.scrollEvent = function()
{
var el = this.el;
var init = this.initTop;
//
var myInt = setInterval(function()
{
var cur = (document.body.scrollTop||document.documentElement.scrollTop)+20;
var myTop = el.offsetTop;
var d = cur-myTop;
if(Math.abs(d)>1) {
if( cur >= init )
{
var y = myTop + d/3;
el.style.top = y+"px";
} else {
el.style.top = init+"px";
clearInterval(myInt);
}
} else {
el.style.top = cur+"px";
clearInterval(myInt);
}
},this.interval);
}
//
var sc = new ScrollChaser('side',200);
sc.init();