ホテルを選ぶとき、これだけは譲れない条件TOP3は?

JavaScriptで初めてOOPを試したところうまくいきません。どこがおかしいのでしょうか?

img要素をアニメーション的に移動させたいと思っており、次のようにコンストラクタとprototypeを使ってクラスを作成し、インスタンスを生成して最下部の関数をイベントハンドラで呼び出してみるのですが実行されません。

//コンストラクタ

function Box(emID,targetX,targetY,speed,timer){
this.element=getElementById("emID");
this.targetX=targetX; //移動先の座標
this.targetY=targetY;
this.speed=speed;
this.timer=timer*1000;
}

//現在の座標取得

Box.prototype.currentXY=function(){
this.currentX=eval(this.element.style.left.replace("px",""));
this.currentY=eval(this.element.style.top.replace("px",""));
}

//移動先までのXY値を徐々に加算

Box.prototype.loopContents=function(){
if(this.currentX<=targetX-0.3 || this.currentY<=targetY-0.3){
this.currentX += (targetX-currentX)/speed;
this.element.style.left = this.currentX+"px";
this.currentY += (targetY-currentY)/speed;
this.element.style.top = this.currentY+"px";
}
else{
clearTimeout();
}
}

//加算を繰り返す

Box.prototype.runLoop=function(){
setTimeout(this.loopContents(),10);
}


//実行関数

function move(emID,targetX,targetY,speed,timer){
alert(emID+"and"+targetX+"and"+targetY+"and"+speed+"and"+timer); //(1)
var mover = new Box(emID,targetX,targetY,speed,timer);
window.alert("check"); //(2)
mover.currentXY(); //現在のXYを取得
setInterval(mover.runLoop(),mover.timer);
}

alertで検査してみるのですが(1)ではemIDの箇所は[object HTMLImageElement]と表示されます。これは問題ないのでしょうか?
また(2)のalertは機能しないようです。
どこがどう設計ミスなのか全くわからず困っています。

A 回答 (3件)

最初の呼び出し方をどのようにしているのか不明ですが…


・emIDがid(文字列)であるのなら、Boxの
 this.element=getElementById("emID"); は""が不要では?(No1様が指摘済み)

>(1)ではemIDの箇所は[object HTMLImageElement]と表示されます
それだと、emIDはid(文字列)ではなく、image要素みたいだけれど、最初に何を渡しているのだろう?

・currentXYの中でevalを使う必要はなさそう
 これは別に問題というわけではないけれど…

・loopContents内で
 targetX、currentX、speed等がそのまま用いられているが、変数が未定義のはず。
 this.~~ってつもりでは?

・clearTimeout(); ってidがないけれど…?
 それに、おおもとのsetIntervalのほうはどうなるの?(ずっとループしっぱなし)

・setTimeout(this.loopContents(),10);
 setInterval(mover.runLoop(),mover.timer);
はセンテンス実行時に各関数が評価されてしまいます。
時間を置いて実行する場合は引数に関数名を…

・↑を修正しても、繰り返し呼び出しには工夫が必要
 (いまのところクロージャ的な方法しか思いつかない。)
    • good
    • 1
この回答へのお礼

ご回答ありがとうございます。

>最初の呼び出し方をどのようにしているのか不明ですが…

imgタグの中でonclick="move(box1,100,100,5,0.5);"と記述し呼び出しています。
box1は別のimg要素のidです。
このbox1がまずいんでしょうか。。

>・currentXYの中でevalを使う必要はなさそう

currentX,currentYを数値として扱いたいので文字列から変換しています。もっとスマートな方法があるのかもしれませんね。

>loopContents内で
 targetX、currentX、speed等がそのまま用いられているが、変数が未定義のはず。
 this.~~ってつもりでは?

ですね。恐縮です


>clearTimeout(); ってidがないけれど…?
 それに、おおもとのsetIntervalのほうはどうなるの?(ずっとループしっぱなし)

setTimeout()からの戻り値をidにして引数に渡すんですね。
そもそもsetTimeout()は必要ないみたいでした。

>・setTimeout(this.loopContents(),10);
 setInterval(mover.runLoop(),mover.timer);
はセンテンス実行時に各関数が評価されてしまいます。
時間を置いて実行する場合は引数に関数名を…

・↑を修正しても、繰り返し呼び出しには工夫が必要
 (いまのところクロージャ的な方法しか思いつかない。)


関数名を文字列にしておく必要があるということが判明したのですが、その理由として文字列にしないと各関数が評価されてしまうからという理解でいいんでしょうか。

一応直せるところは直してみたのですが、やはり動きません。
機構的に何か問題があるのでしょうか。

お礼日時:2010/08/05 01:44

No.1、No.2の繰り返しになりますが。




this.element=document.getElementById("emID");
this.element=document.getElementById(emID);

この2行の違いはわかりますか?
それぞれのthis.elementには何が入ると思いますか?


> ・↑を修正しても、繰り返し呼び出しには工夫が必要

使い方(繰り返し呼び出しの方法)はパターン化していますので、工夫せずともほぼ解説サイトのコピーペーストで行けると思います。
setTimeout、setIntervalの両方を"無理に"使う必要はありません。

setTimeout、setInterval、clearTimeout、clearInterval
それぞれの使い方を再確認して下さい。
その際、setTimeout、setIntervalの戻り値にも注意して下さい。


> imgタグの中でonclick="move(box1,100,100,5,0.5);"と記述し呼び出しています。
> box1は別のimg要素のidです。
alert()で確認されたとおりです。
box1に何が入っているか再確認して下さい。


> Box.prototype.currentXY
結果オーライな感じがしますが、ノーコメントで。


loopContents()関数内で、ところどころ this. が抜けているようです。
    • good
    • 0
この回答へのお礼

ありがとうございます。


>this.element=document.getElementById("emID");
this.element=document.getElementById(emID);
この2行の違いはわかりますか?
それぞれのthis.elementには何が入ると思いますか?

上は()内が単なる文字列となり引数と対応しないのでundefined、下はemIDをidにもつ要素そのものが入るように思えます。
引数として代入される必要があり、なおかつ()内は文字列となる必要があるので、下のように記述して、引数'box1'を渡すという方法が良いと考えました。いかがでしょうか。


>使い方(繰り返し呼び出しの方法)はパターン化していますので、工夫せずともほぼ解説サイトのコピーペーストで行けると思います。
setTimeout、setIntervalの両方を"無理に"使う必要はありません。

クロージャでできないかと考えてみましたが、今の私には敷居が高く行き詰まりました。他の繰り返し呼び出しの方法を調べてみようと思います。



>setTimeout、setInterval、clearTimeout、clearInterval
それぞれの使い方を再確認して下さい。
その際、setTimeout、setIntervalの戻り値にも注意して下さい。

戻り値をclear~()に渡すということですね。set~()の第1引数の形式についてまだ理解不十分な点があります。

>alert()で確認されたとおりです。
box1に何が入っているか再確認して下さい。

引数にbox1を渡し、alert(emID);で見ると[object ~]と出るのでこれはimgオブジェクトそのものが入っているという解釈でいいのでしょうか。
一方'box1'を渡すとそのままbox1とalert()で返されるので、これは単なるid名ということになるということでしょうか。


this.の抜けやemIDの箇所、set~の第一引数をfunction(オブジェクトメソッド){}にするなど修正し、setInterval()1つのみを使って単純に動作させることには成功しました。
もともとsetTimeout()で一定時間後にアクションをスタートさせ、アクションにはsetInterval()を使うという機構を考えていましたが、関数が3重に入れ子になってしまったためにうまくいかなかったということが分かってきました。

だいぶ打開されてきましたがもう少し試行錯誤してみます。

お礼日時:2010/08/05 05:46

何のブラウザでチェックしているのかわかりませんが、最近のブラウザにはコンソールがあるのでエラーメッセージを確認してみてください。


下記行でエラーが発生します。

this.element=getElementById("emID"); // Uncaught ReferenceError: getElementById is not defined

# マルチポストのようなので、URLを記載しておきます。

JavaScriptで初めてOOPを試したところうまくいきません。どこがおかしいのでしょう... - Yahoo!知恵袋
http://detail.chiebukuro.yahoo.co.jp/qa/question …
    • good
    • 0
この回答へのお礼

ご回答頂きありがとうございます。
確かにまずエラーコンソールでチェックしてみるべきですね。
getElementById("emID")の前にdocument.を付け、他のエラーも修正してみましたが、やはり動作しません。もう少し粘ってみようと思います。
もし他にアドバイスがありましたらお願い致します。

お礼日時:2010/08/04 20:14

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