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());
});
我写了一个Javascript函数,假设加载一个充满编号的.png文件的目录。但是,我事先并不知道目录中的项目数。所以我做了一个继续存储图像的功能,直到源给我一个错误。但是当我运行代码时,程序甚至没有进入.onload和.onerror函数,导致无限循环。
编辑:这是我目前的代码。看起来图像被正确分配并推入阵列图像。但是当我尝试将它加载到img标签(currentImage.src)并运行playSequence时,它不会显示。
答案 0 :(得分:1)
您可以使用promises来处理图像的预加载。 将on resolves链接到onload事件并拒绝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画布上绘图。
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();
})
}
要测试我使用ffmpeg使用以下命令剪切视频:
ffmpeg -i input.mp4 -ss 00:00:14.435 -vframes 100 %d.png
我使用devd.io快速创建一个包含脚本和图像以及基本index.html的静态文件夹。
imageroller.js - 使用上面的代码。
var preload = preloadImages('/static/videos/examples/testvid/', 'png', 1);
preload.then(function(value) {
console.log('starting play');
var canvas = document.getElementById("canvas");
play(canvas, value, 24, 720, 400) // ~480p 24fps
.then(function(frame){
console.log('roll finished after ' + frame + ' frames.')
})
});
虽然图像的预加载非常慢,但如果将帧数保持在可接受的水平,则可以制作一些漂亮的循环。
答案 1 :(得分:0)
我还没有测试下面的代码段(并且可能有更清晰的解决方案),但这个想法应该是正确的。基本上我们有一个递归函数{' ': 'h', '4': 'y', '>': '8', 'a': 'c', 'o': 'u'}
,我们传入loadImages()
数组和一个回调函数。我们等待加载当前图像;如果它加载,我们将其推入images
并再次调用images
。如果它抛出错误,我们知道我们已经完成加载,所以我们返回我们的回调函数。如果您有任何问题,请告诉我。
loadImages()
答案 2 :(得分:0)
最佳解决方案是提供服务器端API,预先告诉您目录中有多少图像。 如果无法做到这一点,您应该一个接一个地加载图像,以防止对服务器的过多请求。在这种情况下,我会将图像加载代码放在一个单独的函数中,并在前一个图像成功加载时调用它,如下所示:
private static int dsSize(DataSet ds)
{
int returnValue = 0;
foreach (DataRow dr in ds.Tables[ds.Tables.Count - 1].Rows)
{
int rowSize = 0;
for (int i = 0; i < ds.Tables[ds.Tables.Count - 1].Columns.Count; i++)
{
rowSize += System.Runtime.InteropServices.Marshal.SizeOf(dr[i]);
}
returnValue += rowSize;
}
return returnValue;
}
然后在while循环和loadCallback中调用此函数。