プロが教える店舗&オフィスのセキュリティ対策術

前置き:別に困っているわけでもありません
・こんな質問許されないかも(ご容赦を)
・自分で勉強しろと言われるかも(ごもっとも)
・ごみプログラムがさらにごみプログラムを生んでいるかも(ごめんなさい)
本題:
いつぞやのタイトルくるくるのサンプルを基に、画像がフェードイン、
フェードアウトするオブジェクト指向っぽいスクリプトを作りました。
下のソースです。スタイル属性の変更をwindow.setIntervalを使って
counter値に達するまでループ実行しているだけです。

似たような処理のfadeinクラスとfadeoutクラスを作って、
 fadein.start(ターゲット,インターバルミリ秒);
 fadeout.start(ターゲット,インターバルミリ秒);
でフェードイン、フェードアウトを開始していますが、
fadeinクラスとfadeoutクラスをfadeinoutクラス一つにまとめちゃって、
fadeinoutクラスのメソッド(?)としてfadein、fadeoutを使えるように
するには、どうやって作ればよいのかと言うのが質問です。
本当は、
 var myobj = new fadeinout(ターゲット,インターバルミリ秒);
とインスタンスして
 myobj.fadein;
 myobj.fadeout;
みたく使うためのコーディングがよくわからんのです。
抜本的に書き換えた方がよいのでしょうか...

<作ったサンプル>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja-JP">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>FadeIn/FadeOut</title>
<style type="text/css"></style>
<script type="text/javascript" charset="utf-8">
<!--
var fadein = function (node,interval){
this.counter = 0;
this.target = node;
this.interval = interval;
this.timerId = setInterval((function(that){
return function(){that.loop();};
})(this),this.interval);
this.stop = function () {
this.timerId && clearInterval(this.timerId);
this.timerId = null;
};
this.loop = function(){
this.target.style.width=this.counter+"px";
this.target.style.height=this.counter+"px";
this.target.style.opacity = this.counter / 100;
this.target.style.filter = "alpha(opacity=" + this.counter + ")";
if( ++this.counter>100) this.stop();
};
};
var fadeout = function (node,interval){
this.counter = 100;
this.target = node;
this.interval = interval;
this.timerId = setInterval((function(that){
return function(){that.loop();};
})(this),this.interval);
this.stop = function () {
this.timerId && clearInterval(this.timerId);
this.timerId = null;
};
this.loop = function(){
this.target.style.width=this.counter+"px";
this.target.style.height=this.counter+"px";
this.target.style.opacity = this.counter / 100;
this.target.style.filter = "alpha(opacity=" + this.counter + ")";
if( --this.counter<0) this.stop();
};
};

fadein.start = function(target,interval){
new fadein(target,interval );
}
fadeout.start = function(target,interval){
new fadeout(target,interval );
}

function fadein_s(){
var target=document.getElementById("target");
fadein.start(target,1);
}
function fadeout_s(){
var target=document.getElementById("target");
fadeout.start(target,1);
}


// -->
</script>
</head>
<body>
<div>
<image id="target" src="image/yahagi.png" style="width:0px;height:0px;">
</div>
<button onclick="fadein_s();">フェードイン</button>
<button onclick="fadeout_s();">フェードアウト</button>
</body>
</html>

A 回答 (6件)

こんばんは。

お勉強中の者です。
回答というよりも、自分のお勉強のために一応動作するものを創ってみました。(実は、よくわかっていません)

> var myobj = new fadeinout(ターゲット,インターバルミリ秒);
> とインスタンスして
> myobj.fadein;
> myobj.fadeout;
を指定の仕様と考えて、
var myobj = new fade(ターゲットのid, インターバルミリ秒);
で動作します。
 myobj.fadein()、myobj.fadeout()
(サイズは変わりません。透明度のみ変化)

最後のopaqueの呼び出しを、クロージャで書くとどうやらメモリーリークになるらしい(?)ので、分けて書いてますが、これで対策になっているのかどうかもあやふやです。(特に、DOMをそのまま記憶したりしているのでよけいに)
参考にはならないと思いますが、悪い方の見本にはなるかと…

先日、babu_babooさんと似たようなものを作ったここ(↓)でも同じような指摘が…
http://oshiete1.goo.ne.jp/qa5588925.html

------------------------------------------------
<html>
<head><title>test</title>
<script type="text/javascript">

var fade = function(id, interval) {
this.params = { opacity:100, step:3, op2:0, iId:null};
this.params.id = id;
this.params.interval = interval;
this.params.element = document.getElementById(id);
}

fade.prototype.fadein = function() { this.inout(100); }
fade.prototype.fadeout = function() { this.inout(0); }
fade.prototype.inout = function(o) {
var p = this.params;
p.op2 = o;
if (p.iId) clearInterval(p.iId);
p.iId = setInterval(opaque(this), p.interval);
}

function opaque(obj) {
return function() {
var p = obj.params, tmp = p.opacity;
if (p.op2 > tmp) {
tmp += p.step; if (tmp > p.op2) tmp = p.op2;
} else {
tmp -= p.step; if (tmp < p.op2) tmp = p.op2;
}
p.element.style.filter = 'alpha(opacity=' + tmp + ')';
p.element.style.opacity = tmp/100;
p.opacity = tmp;
if (tmp == p.op2) {
clearInterval(p.iId);
p.iId = null;
}
}
}
</script>
</head>

<body>
<div>
<image id="img1" src="A.jpg" alt=""><br>
<button onclick="Img1.fadein();">fadein</button>
<button onclick="Img1.fadeout();">fadeout</button>
</div>
<hr>
<div>
<image id="img2" src="B.jpg" alt=""><br>
<button onclick="Img2.fadein();">fadein</button>
<button onclick="Img2.fadeout();">fadeout</button>
</div>

<script type="text/javascript">
//オブジェクト定義
var Img1 = new fade('img1', 80);
var Img2 = new fade('img2', 30);
</script>

</body>
</html>
    • good
    • 0
この回答へのお礼

どうもありがとうございます。
すっきりして分かりやすいです。
.prototype で機能やプロパティを追加するコーディング
の方が見やすいし、使いまわししやすそうですね。ちがうかな?

お礼日時:2010/02/03 21:23

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "​

http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="​http://www.w3.org/1999/xhtml"​ lang="ja-JP">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>FadeIn/FadeOut</title>
<style type="text/css"></style>
<script type="text/javascript" charset="utf-8">
<!--
function O(target) {
function fadeInOut() { this.target = target; }
fadeInOut.prototype = {
fadein: function(interval) {
this.counter = 0;
this.interval = interval;
this.timerId = setInterval((function(that) {
return function() {
that.loop();
};
})(this), this.interval);
this.stop = function() {
this.timerId && clearInterval(this.timerId);
this.timerId = null;
};
this.loop = function() {
this.target.style.width = this.counter + "px";
this.target.style.height = this.counter + "px";
this.target.style.opacity = this.counter / 100;
this.target.style.filter = "alpha(opacity=" + this.counter + ")";
if (++this.counter > 100) this.stop();
};
},
fadeout: function(interval) {
this.counter = 100;
this.interval = interval;
this.timerId = setInterval((function(that) {
return function() {
that.loop();
};
})(this), this.interval);
this.stop = function() {
this.timerId && clearInterval(this.timerId);
this.timerId = null;
};
this.loop = function() {
this.target.style.width = this.counter + "px";
this.target.style.height = this.counter + "px";
this.target.style.opacity = this.counter / 100;
this.target.style.filter = "alpha(opacity=" + this.counter + ")";
if (--this.counter < 0) this.stop();
}
}
};
return new fadeInOut;
}

// -->
</script>
</head>
<body>
<div>
<image id="target" src="image/yahagi.png" style="width:0px;height:0px;">
</div>
<script type="text/javascript">
var instance = O(document.getElementById('target'));
</script>
<button onclick="O(document.getElementById('target')).fadein(1);">フェードイン</button>
<button onclick="O(document.getElementById('target')).fadeout(1);">フェードアウト</button>
<button onclick="instance.fadein(1);">フェードイン(インスタンス)</button>
<button onclick="instance.fadeout(50);">フェードアウト(インスタンス)</button>
</body>
</html>

表にあるものを単純に中へ入れただけです。インターバル(引数)は
メソッドで受け取る方が使い勝手がよさそうですね。

これだけ書けるんだから、プロトタイプチェーンについて調べれば
理解するのに時間は掛からないと思います。
    • good
    • 0

>No.2 補足



補足と言うか、いい加減なNo.2は無視の方向で。
突っ込まれる前に、例示として絶えられそうなものにしてみました。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<title>FadeIn/FadeOut</title>
<script type="text/javascript">
function FadeInOut(t) {
this.target = document.getElementById(t) || t;
}
FadeInOut.prototype = {
fadein: function(interval) {
this.counter = 0;
this.timer(interval, 1);
},
fadeout: function(interval) {
this.counter = 100;
this.timer(interval, -1);
},
timer: function(int, n) {
this.stop();
var that = this;
this.timerId = setInterval(function() { that.loop(n); }, int);
},
stop: function() {
this.timerId && (clearInterval(this.timerId), this.timerId = null);
},
loop: function(n) {
this.target.style.width = this.counter + "px";
this.target.style.height = this.counter + "px";
this.target.style.opacity = this.counter / 100;
this.target.style.filter = "alpha(opacity=" + this.counter + ")";
this.counter += n;
if (this.counter < 0 || this.counter > 100) this.stop();
}
};

function createFadeInOut(target) {
return new FadeInOut(target);
}
</script>
</head>
<body>
<div>
<img id="target" src="*.gif" alt="*" style="width:0px;height:0px;">
</div>
<script type="text/javascript">
var FadeInOutObj = createFadeInOut('target');
</script>
<div>
<button onclick="FadeInOutObj.fadein(1);">フェードイン</button>
<button onclick="FadeInOutObj.fadeout(1);">フェードアウト</button>
</div>
</body>
</html>


thisはFadeInOutObj(インスタンスオブジェクト)への参照となるわけですが
FadeInOutObj直属のプロパティとなるのは値が代入されているtarget、counter、timerIdの3つ。
fadein、fadeout、timer、stop、loop、各関数はコンストラクタFadeInOut.prototypeの
メンバとして定義してます。プロパティ(メンバ変数)はインスタンスオブジェクトに。
メソッド(メンバ関数)はコンストラクタ.prototypeに、が基本になるでしょうか。

インスタンスオブジェクトが自身のメンバかようにコンストラクタ.prototypeプロパティへ
アクセスする暗黙的な参照をプロトタイプチェーンと呼びます。

誤った解釈があればフォローお願いします。
    • good
    • 0
この回答へのお礼

解説までしてくれて、どうもありがとうございます。
ご回答をもとにもっと勉強してみます。

お礼日時:2010/02/03 21:27

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">


<title></title>

<body>
<div id="hoge">
こんばんは。お勉強中の、「その2」の者です。
回答というよりも、自分のお勉強のために一応動作するものを創ってみました。
(実は、よくわかっていません)
</div>

<script type="text/javascript">
//@cc_on

function Decorator ( alpha ) {
 //@ this.filter = 'Alpha(opacity=' + alpha + ')';
 this.opacity = alpha / 100 + '';
}


function Starter (callbackfn) {
 this.timerID = (function (o) {
  return setInterval(function () { return callbackfn.call(o); }, o.interval);
 })(this);
}


function Stopper () {
 clearInterval( this.timerID );
 this.timerID = null;
}

//__

function Timer ( interval ) {
 this.timerID = null;
 this.interval = interval || 10;
}


Timer.prototype.start = function ( listener ) {
 return Starter.call( this, listener );
};


Timer.prototype.stop = function ( ) {
 return Stopper.call( this );
};

//__

var Fader = function ( ) {
 this.initializer.apply( this, arguments );
};

Fader.prototype = new Timer;
Fader.prototype.constructor = Fader;


Fader.prototype.initializer = (function ( ) {
 return function ( target, interval, opacity ) {
  this.target = target;
  this.interval = interval;
  this.direction = 0;
  this.step = 1;
  this.setOpacity( opacity );
 };
})();


Fader.prototype.fadeIn = (function ( ) {
 return function ( ) {
  this.stop();
  this.direction = 1;
  this.start( this.loop );
 };
})();


Fader.prototype.fadeOut = (function ( ) {
 return function ( ) {
  this.stop( );
  this.direction = -1;
  this.start( this.loop );
 };
})();
    • good
    • 0

//その2


Fader.prototype.setOpacity = (function ( ) {
 return function ( alpha ) {
  var flag = false;

  if( 0 > alpha ) {
   flag = true;
   alpha = 0;
  } else if( 100 < alpha ) {
   flag = true;
   alpha = 100;
  }

  Decorator.call( this.target.style, this.opacity = alpha );

  return flag;
 };
})();


Fader.prototype.loop = (function ( ) {
 return function ( ) {
  var alpha = this.opacity + this.direction * this.step;
  this.setOpacity( alpha ) && this.stop( );
 };
})();

//__

Fader.buffer = { };

Fader.create = function ( id, interval, opacity ) {
 var e, o;

 if( o = Fader.buffer[ id ] ) {
  o.interval = interval;
  o.setOpacity( opacity );
 } else if( e = document.getElementById( id ) ) {
  opacity = 'number' === typeof opacity ? opacity: 100;
  o = new Fader( e, interval || 10, opacity);
  Fader.buffer[ id ] = o;
 }

 return o;
};

//__

var abc = Fader.create( 'hoge', 20,0 );
document.onclick = function (e) { abc.fadeIn(); }

</script>
</body>
</html>
    • good
    • 0
この回答へのお礼

サンプルのご提供どうもありがとうございます。
いろいろな方からサンプルをいただいたので、
じっくり吟味して、クラスオブジェクト見たいなのを
使いこなせるように、研究してみます。
※最近忙しくて、勉強(趣味)の時間がなかなか取れないのですが....

お礼日時:2010/02/03 21:32

追記。


オブジェクト指向的なプログラムは、いまだに良くわかりません。
勉強になったコードを思い返せば、一つの機能は、1つだけにし、
再利用しやすい形で、細分化されて、それらを組み上げられて
作られているように感じました。

なので、タイマーが必要なときは、それをTimerで上書きするだけで
.start() .stop() が使えるようになります。

例えば、loop()の中に、透明度を計算して、設定までしてしまうのではなく
設定は、seyOpacity()のように、設定だけ。

うまく自分も細分化して、それらを構築できるわけではありませんが
そのように、(なんとなくだけですが)学習したつもり。

それから、書き出しは大文字から始めるそうですよ!
fade×
Fade○

それと、
Fade = function ( ) {
 init: function( ) { ;},
 add: function( ) { ; },
 set: function( ) { ; }
};

のようにすると、大風呂敷をひいて、その中にプログラムを詰め込んで
呼ばれるたびに、それら全部を持って歩くような感じがしています。

Fade = function ( ) {
 this.init.apply( this, arguments );
};


Fade.prototype.init = function () {
 ;
};


Fade.prototype.add = function () {
 ;
};

上のようにすると、必要な所だけ、もろものものがコピーされ
小さい風呂敷だけが、動いているような感じがします

実際これが早いかどうかは定かではありませんが^^;

私はプロのプログラマではありませんが、見易さという点で
普通の改行と、1行空けた改行、2行空けた改行を、最近使い分けるようになりました

ショートコーディングが好きなくせに・・・^^;


それと、.createも、いろいろな書物やらコードをみると new は、隠ぺいした方が良いと
書いたものがありました。なのでこんな形。

(学習の)師は、Fade.bufferを使わずに、Fade[ id ] とかにして hasOwnProperty でチェックしていたのですが
今は、ダブっても言いように、こちらにしています。
これが良いのかはわかりません。
いつもこんなんだから無駄に回答が多いのだろう。
    • good
    • 0
この回答へのお礼

アドバイスありがとうございました。

お礼日時:2010/02/05 18:37

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!