2

JavaScript のインタラクティブなチュートリアル ツールに取り組んでいます。ツールの核となるのは、チュートリアルのスクリプトです。スクリプトは、アニメーションの実行、スピーカーの音声による新しいページの読み込みなど、さまざまな機能をトリガーします。

wrap(); //wrap the page in an iframe
playsound('media/welcome') //playing a sound (duh)
highlight('[name=firstname]'); //animation that highlights an element.
playsound('media/welcome2');
loadpage(page2); //loading a new page

すべての呼び出しには共通点があります。非通常のトリガーがあります。たとえば、この単純なスクリプトでは、最初の呼び出しの iframe が読み込まれると、2 番目の呼び出しがトリガーされます。3 番目のスクリプトは、サウンドが完了するとトリガーされます (つまり、遅延)。アニメーションが完了したら、4 番目の関数をトリガーする必要があります。5 番目のイベントは、イベント (クリックなど) でトリガーする必要があります。

これに対する技術的な解決策は、前の関数のコールバックで関数を呼び出すことです。これはかなり面倒になる可能性があります。関数がライトと呼ばれるソリューションで私が気に入っているのは、少しの頭脳を持っているが、コーディングの経験がない人が独自のスクリプトを作成できることです。これをどのように解決しますか?私はJavaScriptにかなり慣れていないので、明示的に説明していただければ幸いです。

4

2 に答える 2

2

コールバックが最善の策だと思います。乱雑である必要はありません (ただし、完全に理解不能にすることは可能です)。コールバックを受け入れる各関数を作成し、次のような構造を使用して、読みやすい方法で順番に呼び出すことができます。

var loadingSequence = {
    start : function() { wrap(this.playsound); },
    playsound : function() { playsound('media/welcome', this.highlight); },
    highlight : function() { highlight('[name=firstname]', this.playsound2); },
    playsound2 : function() { playsound('media/welcome2', this.loadpage); },
    loadpage : function()  { loadpage(page2); }
};

loadingSequence.start();
于 2013-02-26T23:17:42.317 に答える
2

ビルドごとのソリューションを使用します。あなたのニーズに合ったものが必ずあります。jTourのような単純なもの、またはそれがカバーされていない場合は、 Scriptio のようなもう少し複雑なものこの質問に対する回答のいくつかは、あなたにとっても興味深いものかもしれません。

編集 既存のソリューションを使用したくない場合は、次のようにします。

var runTutorial = (function () {

    // The command object holds all the different commands that can
    // be used by someone for the tutorial. Each of these commands
    // will recive a callback set as their `this`. This
    // callback should be called by your commands when they are done
    // running. The person making the tutorial won't need to know
    // about the callback, the code will handle that.
    var commands = {
        wrap: function () {
            //wrap the page in an iframe
            this();
        },
        playsound: function (soundPath, soundLength) {
            //playing a sound (duh)
            setTimeout(this, soundLength);
        },
        highlight: function (selector) {
            //animation that highlights an element.
            //I'm using jQuery UI for the animation here,
            // but most animation libraries should provide
            // a callback for when the animation is done similarly
            $(selector).effect('highlight', 'slow', this);
        },
        loadpage: function (pageUrl) {
            //loading a new page
            setTimeout(this, 500);
        },
        waitForClick: function () {
            // when we go into the click handler `this` will no
            // longer be availble to us since we will be in a
            // different context, save `this` into `that` so
            // we can call it later.
            var that = this;
            $(document).one('click', function () {
                that();
            });
        }
    },
    // This function takes an array of commands
    // and runs them in sequence. Each item in the
    // array should be an array with the command name
    // as the first item and any arguments it should be
    // called with following as the rest of the items.
    runTutorial = function (commandList) {
        var nextCommand = function () {
            if (commandList.length > 0) {
                var args = commandList.shift();

                // remove the command name
                // from the argument list
                cmd = args.shift(1);

                // call the command, setting nextCommand as `this`
                commands[cmd].apply(nextCommand, args);
            }
        }

        nextCommand();
    };

    return runTutorial;

}()); 

$('#tutorialbutton').click(function() {
    runTutorial([
        ['playsound', 'media/welcome', 1000],
        ['highlight', '[name=firstname]'],
        ['playsound', 'media/welcome2', 1500],
        ['waitForClick'],
        ['loadpage', page2],
        ['playsound', 'media/page2', 100]
    ]);
});

このrunTutorial関数は、実行する順序でコマンドを含む単純な配列とそのパラメーターを受け取ります。コールバックでスクリプトを書いている人を煩わす必要はありませんrunTutorial。これには、ライターがコールバックを管理する必要があるシステムよりも大きな利点があります。明示的なコールバックの場合のように、スクリプトの各行に一意の名前を付けたり、無名関数を無限にネストしたりする必要はありません。コマンドが再生される順序を変更するために何も再配線する必要はありません。配列内でコマンドを物理的に再配置するだけです。

あなたが遊ぶことができるjsfiddle

各コマンドは、コールバック (別名this) を呼び出す前に、アクションが完了するまで待機する必要があります。を使用してフィドルでこれをシミュレートしsetTimeoutます。たとえば、jQuery の.animateforを使用している場合、アニメーションが完了したときに起動するハンドラーがhighlight提供されます。そこに (呼び出し括弧を使用せずに) 貼り付けます。jQuery UI を使用している場合は、「ハイライト」効果が組み込まれているため、次のように実装できます。completethis()

highlight: function (selector) {
    //animation that highlights an element.
    $(selector).effect('highlight', 'slow', this);
},

アニメーションを提供する他のほとんどのライブラリは、使用できる同様のコールバック オプションを提供する必要があります。

再生方法によっては、サウンドのコールバックを制御するのが難しくなる場合があります。使用しているメソッドがコールバックを提供していない場合、またはそれが完了したかどうかを確認するためにポーリングする方法を提供していない場合はplaysound、サウンドの長さをミリ秒単位で取得し、続行する前にその時間を待機する別のパラメーターを追加する必要がある場合があります。 :

playsound: function (soundPath, soundLength) {
    //playing a sound (duh)
    setTimeout(this, soundLength);
},
于 2013-02-26T23:38:59.977 に答える