2017-07-20 18 views
0
var images; 
function preloadTrial(actor, event) { 
    return new Promise(function(res) { 
    var i = 0; 
    images = []; 
    var handler = function(resolve, reject) { 
     var img = new Image; 
     var source = '/static/videos/' + actor + '/' + event + '/' + i + '.png'; 
     img.onload = function() { 
     i++; 
     resolve(img); 
     } 
     img.onerror = function() { 
     reject() 
     } 
     img.src = source; 
    } 
    var _catch = function() { res(images) } 
    var operate = function(value) { 
     if (value) images.push(value); 
     new Promise(handler).then(operate).catch(_catch); 
    } 
    operate(); 
    }) 
} 

function playSequence(time){ 
    var delta = (time - currentTime)/1000; 
    currentFrame += (delta * FPS); 
    var frameNum = Math.floor(currentFrame); 
    if (frameNum >= numFramesPlay) { 
    currentFrame = frameNum = 0; 
    return; 
    }else{ 
    requestAnimationFrame(playSequence); 
    currentImage.src = images[frameNum]; 
    currentTime = time; 
    console.log("display"+currentImage.src); 
    } 
}; 

function rightNow() { 
    if (window['performance'] && window['performance']['now']) { 
    return window['performance']['now'](); 
    } else { 
    return +(new Date()); 
    } 
}; 

currentImage = document.getElementById("instructionImage"); 
// Then use like this 
preloadTrial('examples', 'ex1').then(function(value) { 
    playSequence(currentTime=rightNow()); 
}); 

番号が付けられた.pngファイルでディレクトリが完全に読み込まれると想定されるJavascript関数を記述しました。ただし、あらかじめディレクトリ内の項目数はわかりません。だから私はソースが私にエラーを与えるまで画像を保存し続ける関数を作った。しかし、私がコードを実行すると、プログラムは.onloadと.onerror関数にも入っていないので、無限ループになります。JavaScript onloadとonerrorが呼び出されていない

編集:これは私の現在のコードです。画像が正しく割り当てられ、アレイ画像にプッシュされるように見えます。しかし、imgタグ(currentImage.src)にロードしてplaySequenceを実行しようとすると、表示されません。

+0

私は '/ static'がルート('/')ディレクトリに' static'というフォルダを見つけようとしていると思います。どのようなファイル構造が設定されていますか?それを '。/ static'や' static'に変更することは何ですか? –

+0

@J。陳いい、それは問題ではない。これはforループで動作します。しばらく使っているのは、画像の数が分からないからです。 –

+0

'on 'を取り除く。それは、スクリプトではなくHTML用です。 –

答えて

1

画像のプリロードを処理するために約束を使うことができます。 サイクルを終了するには、onloadイベントとreject onerrorで解決を連鎖させます。

function preloadImages(baseurl, extension, starter) { 
    return new Promise(function(res) { 
    var i = starter; 
    var images = []; 
    // Inner promise handler 
    var handler = function(resolve, reject) { 
     var img = new Image; 
     var source = baseurl + i + '.' + extension; 
     img.onload = function() { 
     i++; 
     resolve(img); 
     } 
     img.onerror = function() { 
     reject('Rejected after '+ i + 'frames.'); 
     } 
     img.src = source; 
    } 
    // Once you catch the inner promise you resolve the outer one. 
    var _catch = function() { res(images) } 
    var operate = function(value) { 
     if (value) images.push(value); 
     // Inner recursive promises chain. 
     // Stop with the catch resolving the outer promise. 
     new Promise(handler).then(operate).catch(_catch); 
    } 
    operate(); 
    }) 
} 

動画プレーヤーをシミュレートするには、HTML5キャンバスに描画することができます。

ffmpeg -i input.mp4 -ss 00:00:14.435 -vframes 100 %d.png

そして、私はすぐにスクリプトと画像や基本を含む静的なフォルダを作成するdevd.ioを使用:私は、次のコマンドを使用してビデオをカットするのffmpegを使用しテストする

function play(canvas, imagelist, refreshRate, frameWidth, frameHeight) { 
    // Since we're using promises, let's promisify the animation too. 
    return new Promise(function(resolve) { 
     // May need to adjust the framerate 
     // requestAnimationFrame is about 60/120 fps depending on the browser 
     // and the refresh rate of the display devices. 
     var ctx = canvas.getContext('2d'); 
     var ts, i = 0, delay = 1000/refreshRate; 
     var roll = function(timestamp) { 
      if (!ts || timestamp - ts >= delay) { 
       // Since the image was prefetched you need to specify the rect. 
       ctx.drawImage(imagelist[i], 0, 0, frameWidth, frameHeight); 
       i++; 
       ts = timestamp; 
      } 
      if (i < imagelist.length) 
       requestAnimationFrame(roll); 
      else 
       resolve(i); 
     } 
     roll(); 
    }) 
} 

index.html。

imageroller.js - 上記のコードを使用します。

イメージのプリロードはかなり遅いですが、フレーム数を許容可能なレベルに保つと、素晴らしいループを作成できます。

+0

更新状況とコードをご覧ください。 –

+1

@AlexKerが私の答えを更新しました。 – T4rk1n

+0

私の古い方法のアニメーションには何が問題であり、それを修正する方法はありませんか?答えをbtwいただきありがとうございます。 –

0

私は以下のスニペットをテストしていません(そしてもっと清潔な解決策があります)が、そのアイデアは正しいはずです。基本的には、再帰関数loadImages()があり、images配列とコールバック関数を渡します。現在のイメージが読み込まれるまで待ちます。ロードされた場合はimagesにプッシュし、もう一度loadImages()と呼び出します。エラーが発生した場合、ロードが完了していることがわかっているので、コールバック関数を返します。ご質問がある場合はお知らせください。

function preloadTrial(actor, event) { 
 
    let images = []; 
 
    loadImages(images, actor, event, function() { 
 
    // code to run when done loading 
 
    }); 
 
}; 
 

 
function loadImages (images, actor, event, callback) { 
 
    let img = new Image(); 
 
    let i = images.length; 
 
    let source ='/static/videos/'+actor+'/'+event+'/'+i+'.png'; 
 
    img.onload = function() { 
 
    images.push(img); 
 
    return loadImages(images, actor, event, callback); 
 
    } 
 
    img.onerror = function() { 
 
    return callback(images); 
 
    } 
 
    img.src = source; 
 
}

+0

私の更新コードをご覧ください。ありがとう! –

0

最適解がディレクトリにありますどのように多くの画像を、事前にわかりますサーバー側のAPIを提供するだろう。 これが不可能な場合は、イメージを次々にロードして、サーバーへの過剰な要求を防ぐ必要があります。この場合、私は別の関数で画像の読み込みのコードを入れて、前の画像がそうのように、正常にロードされた場合は、それを呼び出します。

function loadImage(actor, event, i, loadCallback, errorCallback) { 
var image = new Image(); 
var source ='/static/videos/'+actor+'/'+event+'/'+i+'.png'; 
image.onload = loadCallback; 
image.onerror = errorCallback; 
image.src = source; 
return image; 
} 

してからwhileループにし、loadCallbackでこの関数を呼び出します。

関連する問題