Javascript 如何缓存光栅化的图像
我正在做一个像索尼这样的停止镜头滚动控制播放网站 考虑到stop-shot技术,我面临的问题是,在浏览器将图像绘制到屏幕上之前,将图像光栅化所需的时间。在手机上需要很多时间。可能调整图像的大小会占用大部分cpu,但我不确定。以下是我显示框架的方式: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-
<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
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 = '...';