Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/433.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何缓存光栅化的图像_Javascript_Canvas_Html5 Canvas - Fatal编程技术网

Javascript 如何缓存光栅化的图像

Javascript 如何缓存光栅化的图像,javascript,canvas,html5-canvas,Javascript,Canvas,Html5 Canvas,我正在做一个像索尼这样的停止镜头滚动控制播放网站 考虑到stop-shot技术,我面临的问题是,在浏览器将图像绘制到屏幕上之前,将图像光栅化所需的时间。在手机上需要很多时间。可能调整图像的大小会占用大部分cpu,但我不确定。以下是我显示框架的方式: <div style=" position: fixed; top:0; right:0; bottom:0; left:0; background-image: url(...); background-

我正在做一个像索尼这样的停止镜头滚动控制播放网站

考虑到stop-shot技术,我面临的问题是,在浏览器将图像绘制到屏幕上之前,将图像光栅化所需的时间。在手机上需要很多时间。可能调整图像的大小会占用大部分cpu,但我不确定。以下是我显示框架的方式:

<div 
  style="
    position: fixed;
    top:0; right:0; bottom:0; left:0;
    background-image: url(...);
    background-position: center;
    background-size: cover;
  "
></div>

画布绘制源是图像和视频对象(以及其他一些现在不相关的源)。因此,如果在初始下载和渲染期间出现了不必要的延迟,那么画布将花费更长的时间,因为传入的图像必须首先渲染到图像对象上,然后再次渲染到画布上——两步而不是一步

您的答案不在canvas元素中,因此您回到了通常的解决方案:通过降低图像质量(质量较低的jpg)来减少下载的图像位的数量


您还可以(如您所述)将所有图像预加载并缓存到
new Image
s中,以便在需要时立即使用。通常的成本是:缓存图像的内存使用量增加,并且在下载所有必需的图像时,应用程序启动会延迟。

Ref comments-有一种方法可以预缓存视频帧。每个帧将使用位图的完整内存块(在任何情况下,预加载的图像序列也是如此)

缓存进程
  • 创建“离线”视频元素
  • 将视频源设置为
    preload
    设置为
    auto
  • 您需要知道帧速率(典型情况:美国/日本为30 fps,欧洲为25 fps),并在此基础上计算时间增量,即
    1/fps
  • 对每个
    currentTime
    更新使用
    timeupdate
    事件,因为设置当前时间是异步的
在视频中选择一个切入点,缓存(由于事件周期,这可能需要一段时间),使用画布元素为每个帧存储到帧缓冲区。然后在需要时播放缓冲区(这也使您能够如下图所示向后播放视频,这是浏览器尚不支持的功能)

例子 此示例将从网络加载视频,将90帧(每秒30帧时为3秒)缓存到内存中,然后在窗口中播放乒乓球序列(您看到的图像显然来自缓存):

var canvas=document.querySelector(“canvas”),
ctx=canvas.getContext(“2d”),
视频=document.createElement(“视频”),
帧=[],
w=画布宽度,h=画布高度;
video.addEventListener(“canplay”,缓存);
video.preload=“自动”;
video.src=”http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";
函数缓存(){
this.removeEventListener(“canplay”,cache);//删除以避免召回
var fps=30,//假设为30 fps
增量=1/fps,//时间增量
计数=0,//当前缓存的帧
最大值=fps*3,//3秒
div=document.querySelector(“div”);//仅供参考
this.addEventListener(“timeupdate”,cacheFrame);//时间更新为aync
this.currentTime=19;//从初始时间开始
函数cacheFrame(){
div.innerHTML=“缓存帧:”+计数;
如果(计数+<最大值){
//为帧缓冲区创建画布;
var canvas=document.createElement(“画布”),
ctx=canvas.getContext(“2d”);
canvas.width=this.videoWidth;//画布大小=视频帧
canvas.height=this.videoHeight;
ctx.drawImage(视频,0,0);//绘制当前帧
frames.push(画布);//存储框架
this.currentTime+=delta;//更新时间,等待。。
}
否则{
this.removeEventListener(“timeupdate”,cacheFrame);//删除!!
play();//播放缓存的序列
}
}
}
//演示缓存的帧
函数播放(){
var电流=0,最大=frames.length,dlt=1,
div=document.querySelector(“div”),
toggle=false,
mem=max*video.videoWidth*video.videoHeight*4;//始终为RGBA
mem=(mem/1024)/1024;//mb
ctx.fillStyle=“红色”;
(函数循环(){
toggle=!toggle;//将FPS切换为30 FPS
请求动画帧(循环);
如果(切换){
div.innerHTML=“播放帧:”+当前+
“(原始成员:“+mem.toFixed(1)+”mb)”;
drawImage(帧[current],0,0,w,h);//使用帧缓冲区
ctx.fillRect(0,0,当前/最大*w,3);
电流+=dlt;
如果(!current | | current==max-1)dlt=-dlt;//pong-pong
}
})();
}
html,正文{宽度:100%;高度:100%}
正文{边距:0;溢出:隐藏;背景:#aaa}
div{font:bold 20px单空格;padding:12px;color:#000}
画布{z-index:-1;位置:固定;左侧:0;顶部:0;宽度:100%;高度:100%;最小高度:400px}
预加载视频。。。等等,等等。。。

这个问题在这里已经得到了非常深入的回答-@BenRondeau,但它不是这样吗?你能做一个代码笔或其他东西来证明这一点吗?位图图像已经被定义为光栅化,你还提到索尼的网站使用视频(+CSS)。你的意思是,如何从视频中捕获一帧供以后使用?@KenFyrstenberg它是光栅化的,但用于特定的像素贴图。然后,即使我在同一个像素图中绘制图像,图像也需要首先解码。但这不仅仅是因为,在实践中,所有设备都有不同的大小,因此图像需要在解码后调整大小(重新命名)。如果是这样,那么我同意,画布是不可能的。我只是想知道索尼为什么选择帆布。。继续
var image = new Image();
image.src = '...';