我对我正在进行的实验有疑问。
我的计划是在整个页面上拥有美丽闪亮的星星背景。 使用那个令人难以置信的教程(http://timothypoon.com/blog/2011/01/19/html5-canvas-particle-animation/),我设法得到了完美的背景。 我使用静态画布来显示静态星星和动画画布。
事实是它非常渴望记忆!在Chrome和Opera上它运行得相当顺利,但是在Firefox或IE平板电脑上,渲染每个帧等都是一团糟......在HEIGHT很大的页面上情况更糟。
所以我进行了一些优化:
- 使用缓冲区画布,问题是createRadialGradient,每帧调用1500次
- 使用一个大的缓冲画布,每个星星使用1个画布,只在init上调用createRadialGradient。
- 删除缓冲画布并将每个星形画布绘制到主要画布
最后一次优化是我能做到的最好的,所以我写了一个小提示,显示现在的代码是什么。
//Buffering the star image
this.scanvas = document.createElement('canvas');
this.scanvas.width=2*this.r;
this.scanvas.height=2*this.r;
this.scon=this.scanvas.getContext('2d');
g = this.scon.createRadialGradient(this.r,this.r,0,this.r,this.r,this.r);
g.addColorStop(0.0, 'rgba(255,255,255,0.9)');
g.addColorStop(this.stop, 'rgba('+this.color.r+','+this.color.g+','+this.color.b+','+this.stop+')');
g.addColorStop(1.0, 'rgba('+this.color.r+','+this.color.g+','+this.color.b+',0)');
this.scon.fillStyle = g;
this.scon.fillRect(0,0,2*this.r,2*this.r);
这就是我需要你的地方:
- 根据用户性能调整闪亮星星数量的方法
- 优化提示
提前感谢所有关心帮助我的人,如果我犯了语法错误,我会道歉,我的英语并不完美。
修改 感谢您的反馈, 让我解释整个过程, 每个星星都拥有不同的渐变和大小,这就是为什么我将它存储到个人画布中,闪光效果只能通过使用drawImage在主画布上缩放画布来完成。
我认为最好的方法是在缓冲画布上预先渲染50或100个不同的星星,然后挑选和绘制一个随机的星星,你认为不是吗?
EDIT2
根据术士的建议更新小提琴,一个预渲染的星,缩放以匹配当前大小。星星不那么漂亮,但整个事情要顺利得多。
EDIT3
更新了使用精灵表的小提琴。华丽!!!!
//generate the star strip
var len=(ttlm/rint)|0;
scanvas = document.createElement('canvas');
scanvas.width=len*2*r;
scanvas.height=2*r;
scon=scanvas.getContext('2d');
for(var i=0;i<len;i++){
var newo = (i/len);
var cr = r*newo;
g = scon.createRadialGradient(2*r*i+r,r,0,2*r*i+r,r,(cr <= 2 ? 2 : cr));
g.addColorStop(0.0, 'rgba(200,220,255,'+newo+')');
g.addColorStop(0.2, 'rgba(200,220,255,'+(newo*.7)+')');
g.addColorStop(0.4, 'rgba(150,170,205,'+(newo*.2)+')');
g.addColorStop(0.7, 'rgba(150,170,205,0)');
scon.fillStyle = g;
scon.fillRect(2*r*i,0,2*r,2*r);
}
编辑4(最终)
动态明星作品
function draw() {
frameTime.push(Date.now());
con.clearRect(0,0,WIDTH,HEIGHT);
for(var i = 0, len = pxs.length; i < len; i++) {
pxs[i].fade();
pxs[i].draw();
}
requestAnimationFrame(draw);
if(allowMore === true && frameTime.length == monitoredFrame)
{
if(getAvgTime()<threshold && pxs.length<totalStars )
{
addStars();
}
else
{
allowMore=false;
static=true;
fillpxs(totalStars-pxs.length,pxss);
drawstatic();
static=false;
}
}
}
这是更新的最终小提琴,包括spritesheet,动态星星创作和几个优化。如果你看到别的什么我应该更新,不要犹豫。
POST EDIT 重新启用流星/原型对象/摆脱Jquery
http://jsfiddle.net/macintox/K8YTu/32/
感谢所有帮助过我的人,这非常友善和有教育意义,我希望有时会对某人有所帮助。
Aesdotjs。 PS:我很高兴。经过测试,该脚本甚至可以在每个浏览器上顺利运行IE9。亚塔!!
答案 0 :(得分:2)
如何在径向发光的各个阶段创建一个恒星的spritesheet。
您甚至可以使用canvas来初始创建spritesheet。
然后使用context.drawImage(spritesheet,spriteX,spriteY,starWidth,starHeight)显示星号。
可以非常快速地将Spritesheet图像绘制到屏幕上。
您可以通过将spritesheet分成单个星形图像来进一步优化。
祝你的项目好运:))
答案 1 :(得分:2)
要衡量用户设置的功能,您可以实现一个动态星形创建器,它会停在某个阈值。
例如,在您的代码中,您可以定义要绘制的最小星数。然后在主循环中测量时间,如果绘制星星的时间小于最大阈值,则再添加10颗星(我只是在这里抛出一个数字)。
没有多少人知道requestAnimationFrame
给它所调用的函数一个参数(DOMHighResTimeStamp)给出了自上次请求以来花费的毫秒时间。这将帮助您跟踪负载,因为我们知道每帧60帧/秒约为16.7毫秒,我们可以在此范围内设置一个阈值,这是最佳的,并且仍然允许其他浏览器的一些开销。
代码可能如下所示:
var minCount = 100, /// minimum number of stars
batchCount = 10, /// stars to add each frame
threshold= 14, /// milliseconds for each frame used
allowMore = true; /// keep adding
/// generate initial stars
generateStarts(minCount);
/// timeUsed contains the time in ms since last requestAnimationFrame was called
function loop(timeUsed) {
if (allowMore === true && timeUsed < threshold) {
addMoreStars(batchNumber);
} else {
allowMore = false;
}
/// render stars
requestAnimationFrame(loop);
}
请注意,这有点简化了。您需要首先运行几轮并测量平均值才能使这项工作更好,并且当您添加星星时(并且由于其他浏览器操作)将会达到峰值。
所以添加星星,测量几轮,如果平均值低于阈值则添加星星并重复。
至于优化精灵表是最佳选择。而且他们不必只是成为明星(我将在下面解释)。
梯度和弧是这种应用的昂贵部分。即使在预渲染单个恒星时,由于插值等原因也需要调整这么多星的大小。
当出现大量昂贵的操作时,最好对内存使用做出妥协并预先渲染所有内容。
例如:首先使用渐变和圆弧渲染大星,渲染各种尺寸。 使用该星形将其他尺寸绘制为具有相同单元尺寸的星条。
现在,使用精灵表仅绘制星数的一半并绘制精灵表的剪切部分(并且不会重新调整大小)。然后将画布旋转90度并将画布本身在其自身的顶部绘制在不同的位置(画布本身就变成了一个大的“精灵表”)。
旋转90度并不像其他角度(0,90,180,270被优化)那样性能饥渴。这将给你一个幻想,即拥有实际数量的恒星,并且由于它被旋转,我们无法检测到容易的重复模式。
帆布的单drawImage
次操作比所有星星的许多小型绘制操作要快。
(当然,你可以多次这样做,而不是在你开始看到模式之前一次到达一个点 - 对于多少,大小等没有关键答案,所以找到正确的平衡是总是一个实验)。
其他优化只能使用整数位置和大小。当你使用浮点数时,子像素被激活,这是昂贵的,因为浏览器需要计算偏移像素的抗锯齿。
使用整数值有助于不需要子像素(但这并不意味着如果不是1:1维度,图像将不会被插值)。
您还可以通过使用4上可分割的大小和位置来帮助底层的低 - 低位图处理一点点。这与内存复制和低级削波有关。您总是可以制作多个精灵表来变换可在4上分割的单元格中的位置。
这种技巧在较慢的计算机(即典型的消费者规格计算机)上更有价值。
关闭图像的抗锯齿功能。这将有助于提高性能,但会给星星带来更粗略的结果。要关闭图像抗锯齿,请执行以下操作:
ctx.webkitEnableImageSmoothing = false;
ctx.mozEnableImageSmoothing = false;
ctx.enableImageSmoothing = false;
只要您使用drawImage
渲染星星,您就可以看到效果明显改善。
缓存您可以缓存的所有内容,即星形图像和变量。
执行此操作stars.length
时,浏览器的解析器需要首先找到stars
,然后遍历该树以查找length
- 每轮(这可能会在某些浏览器中进行优化)。
如果你先将它缓存到变量var len = stars.length
,浏览器只需要遍历树和分支一次,在循环中只需查找本地范围即可找到变量len
更快。
您还可以将分辨率降低一半,即。以目标大小的一半做所有事情。在最后一步中,将渲染放大到完整尺寸。这将最初节省75%的渲染区域,但结果会给你一点低分辨率的外观。
在专业视频领域,当物体动画(主要是移动)时,我们经常使用低分辨率作为眼睛/大脑补丁(或无法检测)当物体移动时如此多的细节,因此不那么引人注目。如果这可以帮助必须在这里测试 - 也许不是因为星星实际上没有移动,但值得尝试第二个好处:提高性能。
答案 2 :(得分:1)
<强> 1。最大限度地减少与DOM相关的操作;
在LINE 93中,您正在创建画布:
this.scanvas = document.createElement('canvas');
您只需要一个画布而不是此画布。将画布创建移动到初始化步骤。
<强> 2。使用画布的整数坐标;
第3。使用对象池设计模式来提高性能。
<强> 4。在for循环中缓存长度变量:
for(var i = 0; i < pxs.length; i++) {...
}
更好:
for(var i = 0, len = pxs.length; i < len; i++) {
...
}
注意:不要将jquery与原生js混合使用。