前置き:別に困っているわけでもありません
・こんな質問許されないかも(ご容赦を)
・自分で勉強しろと言われるかも(ごもっとも)
・ごみプログラムがさらにごみプログラムを生んでいるかも(ごめんなさい)
本題:
いつぞやのタイトルくるくるのサンプルを基に、画像がフェードイン、
フェードアウトするオブジェクト指向っぽいスクリプトを作りました。
下のソースです。スタイル属性の変更を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>
No.1
- 回答日時:
こんばんは。
お勉強中の者です。回答というよりも、自分のお勉強のために一応動作するものを創ってみました。(実は、よくわかっていません)
> 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>
どうもありがとうございます。
すっきりして分かりやすいです。
.prototype で機能やプロパティを追加するコーディング
の方が見やすいし、使いまわししやすそうですね。ちがうかな?
No.2
- 回答日時:
<!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>
表にあるものを単純に中へ入れただけです。インターバル(引数)は
メソッドで受け取る方が使い勝手がよさそうですね。
これだけ書けるんだから、プロトタイプチェーンについて調べれば
理解するのに時間は掛からないと思います。
No.3
- 回答日時:
>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プロパティへ
アクセスする暗黙的な参照をプロトタイプチェーンと呼びます。
誤った解釈があればフォローお願いします。
No.4
- 回答日時:
<!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 );
};
})();
No.5
- 回答日時:
//その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>
サンプルのご提供どうもありがとうございます。
いろいろな方からサンプルをいただいたので、
じっくり吟味して、クラスオブジェクト見たいなのを
使いこなせるように、研究してみます。
※最近忙しくて、勉強(趣味)の時間がなかなか取れないのですが....
No.6ベストアンサー
- 回答日時:
追記。
オブジェクト指向的なプログラムは、いまだに良くわかりません。
勉強になったコードを思い返せば、一つの機能は、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 でチェックしていたのですが
今は、ダブっても言いように、こちらにしています。
これが良いのかはわかりません。
いつもこんなんだから無駄に回答が多いのだろう。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- JavaScript jQueryでのドラッグアンドドロップについて 1 2022/07/07 21:04
- JavaScript jQueryでのドラッグアンドドロップについて 1 2022/07/30 09:10
- JavaScript 1日1回引けるJavaScriptおみくじについて 1 2022/12/12 22:28
- JavaScript jqueryを使ったスムーススクロールのコードを書いたのですが、HTMLコード内にある、a butt 2 2022/04/14 10:59
- JavaScript html5に変えるとスライドショーが消えてしまった。 3 2022/03/26 19:53
- JavaScript スマフォではボタンを表示させたくない 2 2023/01/20 14:26
- PHP style.cssのjQuery条件付きcssが機能しない 4 2022/07/17 18:27
- JavaScript セレクトボックスを2つ設けて選択して初めてメッセを表示 1 2022/07/27 12:15
- JavaScript switch文のswitch(n)の部分を複数の値にするか、if文に変えてほしいです。 1 2022/07/27 17:18
- JavaScript 入力フォームの javascript で メールアドレスの正規チェックをを行い、ボタンをクリックして 2 2022/04/27 16:06
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
idを使わずにonclickで自身の要...
-
functionから別のfunctionを実...
-
drawImageの描画順序の指定につ...
-
jqueryのグローバル変数とロー...
-
jQuery 同じ処理を関数にまとめ...
-
無名関数を使うメリットは何で...
-
クリックすると上に開くアコー...
-
AJAXでサイト存在チェック時、...
-
function(e)の意味を教えてくだ...
-
変数のスコープの問題?
-
ajax反映後のjqueryが動かない
-
XMLHttpRequestでキャッシュを...
-
オンマウスでテキストを表示す...
-
google apps scriptの終了のさせ方
-
C#テキストボックスの文字を配...
-
JavaScript window.openで開く...
-
C#OpenCv V4にのエラーに関する...
-
同じIDで定義した要素の配列を...
-
Boolean型配列中のTrueの有無を...
-
<a>タグのテキストを取得
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
functionから別のfunctionを実...
-
idを使わずにonclickで自身の要...
-
関数でy=g(x)のgとは何の略です...
-
jslintのエラーについて質問
-
jQueryの :not() .not() が有効...
-
クリックすると上に開くアコー...
-
jQueryのプラグイン「Skitter」...
-
関数名をテキストから読み込む...
-
小数点以下を5刻みで表示
-
XMLHttpRequestでキャッシュを...
-
jQueryでzipを解凍読み込みする...
-
Matlabで自作関数をオーバーロード
-
javascript(jQuery)でセル内...
-
要素名がスペースを含む場合のj...
-
ページ内に複数表がある場合のT...
-
処理前の「お待ちください」
-
JS 頭文字が大文字について
-
HTML5でファイルドラッグ&ドロ...
-
Javascriptリアルタイムエラー...
-
getElementByIdを使用したグロ...
おすすめ情報