-
ID:pqf65Z さんの質問

jQueryに詳しいかたお助けください。

とあるjQueryプラグインのようなものを作成したのですが、読み込む場所によって結果が違ってしまいます。

具体的には特定のdiv要素に配置した
http://retasretas.github.io/spriteArea/ff6_suripulu.png
のようなゲームで使われるようなスプライト画像をアニメーションさせるプログラムなのですが、
head内にjQueryと当プラグインを読み込むと正常に動作するのですが、
同じ順番でbody閉じタグの直前に置いた場合は読み込む度にうまくいったりいかなかったりと結果が変わってしまいます。
最近ではhead内よりも、body閉じ直前で読み込ませるほうが主流なので、できればそのようにしてもちゃんと動作するようにしたいです。

ですが、いろいろ試しましたが私の知識では解決ができませんでした。

具体的なデモとソースはこちらです。手直しのほどよろしくお願いします。

うまく行く例(head内) http://retasretas.github.io/spriteArea/index.html
いかない例(body閉じ直前) http://retasretas.github.io/spriteArea/index2.html

ソース https://github.com/retasretas/spriteArea

みんなの回答 5 件

ID:IfZE7f さんの回答

どっちも動いてるけど@Windows7/Chrome

ID:IfZE7f

あ、動いたり動かなかったりするのか。

imgList.load(function(){
↑この辺があやしいような

ID:pqf65Z

該当部分を
imgList.each(
に変えたところ、ローカルではどちらでもうまく動くのですがサーバー上だとどちらも動かなくなってしまいました。
うーん、わからん

ID:.iyPL. さんの回答

関係ないですけど、;(function($){ってどういう意味なんですか?
セミコロンから始めてるのは初めて見ました。

こういう記号を含む検索キーワードってググってもヒットしないから、
調べようとしてもわからないんです。。。

良かったら教えてください^^;

ちなみに、この手の質問はstackoverflowに投稿して質問すると、数分で解決する場合が多いですよ。

ID:6iNhfO

「;」から始めるのはプラグインで良く書く手法で、プラグインを読み込ませる前に書かれているコードのセミコロンがコーダーのミスで抜けていたりした場合でも、自分の書いたプラグインの先頭で「;」を記述しておく事で、プラグインの前に書かれているコードと合体してしまって動かなくなるのを防ぐ為に書きます。

ID:pqf65Z

ありがとうございます。
stackoverflowは英語で質問しないといけないので、英語できないのでこちらで質問しましたw

最初のセミコロンについては上記の方の通りです、

ID:6iNhfO さんの回答

軽く見ただけで、実際に動作させながらデバッグしないと確実な回答はできないのですが、上の方と同じでimgList.loadが怪しいような気がします。

loadメソッドは画像の読み込み完了時をトリガーとしてイベントが発生するのですが、本来
1.loadイベントバインド
2.画像の読み込み完了(loadイベント発生)

とならなければならない所、このjsファイルをbody閉じタグ直前に記述する事で、
1.画像の読み込み完了(loadイベント発生)
2.loadイベントバインド(もうすでにloadイベントが発生済みなのでなにも処理が行われない)

になってそうな気がします。

ID:6iNhfO

imgList.load(function(){
console.log("img load completed!");
var sprite = new initSprite([cellWidth, cellHeight], fps, this, cellWidth, cellHeight);
sprite.initCSS();
sprite.next();
});

上記の「console.log("img load completed!");」がコンソールに出力されていないのであれば、ほぼほぼ上記の理由だと思います。

ID:2Il9W2 さんの回答

$(function(){ … });はDOMContentLoadedイベントのことなので、DOMがロードされた時に発火するイベントです。
なので、imgがまだロードできてないときは動かないんだと思います。

なので、$(function(){ … });よりwindow.onload = function(){}を使うのが一番シンプルかもです。

ただ、window.onloadは複数使うと、1つしか動かなくなるので、addEventLintenerでloadイベントを発火させた方がよいかも。

// 実行部分の関数
function fogefoge(){
…画像とかの処理
}

if (window.addEventListener) {
window.addEventListener("load", fogefoge, false);
} else if (window.attachEvent) { //for IE
window.attachEvent("onload", fogefoge);
} else {
window.onload = fogefoge;
}

実際試してないですが、どうでしょ?
てか、W3Qってマークダウンとかないんですね。。書きづらい…。

ID:2Il9W2

あれ、でもhead内だと動くのか(;゚∀゚)
逆かと思ってた…。

ID:pqf65Z さんの回答

今現在
imgList.load(...

imgList.each(...
に変更しました。これでも動かないようです。

ID:IfZE7f

それは改悪になってると思う。
load なら、読み込み待ちになっていたのを、読み込みを待たず実行になってるから。
そもそも、↓のソースはクラスの中に含めてしまってよいのでは?
sprite.initCSS();
sprite.next();

imgList.load(...だと、imgListの中のどれかが読み込み完了した時点で発火してしまうと思うのだけれど、クラスの中でloadを使えば、それぞれの画像について読み込み待ちできるはず。

ID:pqf65Z

loadにすると画像より前にスクリプト読み込みタグを置いた場合はいいんですけどbody閉じ直前に置いた場合にうまく動かないみたいです。

現在、ソースはeachのままinitとnextをクラス内部に移しましたが、画像より後置の場合はうまくいって、前置の場合は読み込む度に結果が異なる状態になりました。

ID:IfZE7f

なるほど、loadが発生しないんですね。
なら、completeで読み込み完了かどうかで分岐してみるとか、
imgList.each(function( i, dom ){
if ( dom.complete ) { // 読み込み完了かどうか
var sprite = new initSprite([cellWidth, cellHeight], fps, this, cellWidth, cellHeight);
}
else {
$(dom).load( function() {
var sprite = new initSprite([cellWidth, cellHeight], fps, this, cellWidth, cellHeight);
});
}
});

window全体の読み込み完了後に処理を走らせるとか。
$(window).one( ’load’, function() {
// ここに開始処理を入れる
});

最終更新日:2013-12-22 (4,589 views)

関連するトピックス

ページ上部に戻る