Javascript 画布:设置简单星形场的动画
我对画布比较陌生。在寻找我的脚,我创造了一个简单的街机游戏 我的问题是关于CPU性能/效率 我正在创建100个随机定位的白点作为黑色背景上的星星。在每个requestAnimationFrame上,星星向左移动一个像素,当它们到达最左侧时,该列像素被放置在屏幕最右侧 使用requestAnimationFrame调用以下函数:Javascript 画布:设置简单星形场的动画,javascript,html,performance,animation,canvas,Javascript,Html,Performance,Animation,Canvas,我对画布比较陌生。在寻找我的脚,我创造了一个简单的街机游戏 我的问题是关于CPU性能/效率 我正在创建100个随机定位的白点作为黑色背景上的星星。在每个requestAnimationFrame上,星星向左移动一个像素,当它们到达最左侧时,该列像素被放置在屏幕最右侧 使用requestAnimationFrame调用以下函数: bgAnimateId = requestAnimationFrame( scrollBg ); function scrollBg() { var imgDa
bgAnimateId = requestAnimationFrame( scrollBg );
function scrollBg() {
var imgData = ctx.getImageData( 0, 0, 1, canvas.height );
var areaToMoveLeft = ctx.getImageData( 1, 0, canvas.width-1, canvas.height );
ctx.putImageData( areaToMoveLeft, 0, 0 );
ctx.putImageData( imgData, canvas.width-1, 0 );
bgAnimateId = requestAnimationFrame( scrollBg );
}
我关心的是-是创建100个小画布元素(或100个div)并制作动画更好,还是使用我上面使用的像素方法更好
非常感谢您提前提供的帮助/指导:-)事实证明,
context.getImageData
和context.putImageData
执行起来非常昂贵,100张画布太多了
因此,这里有一个创建高效平移星场的计划:
使用context.drawImage
非常有效,执行起来也不太昂贵
下面介绍如何在画布上绘制随机星域,然后将该画布另存为图像:
// draw a random starfield on the canvas
bkCtx.beginPath();
bkCtx.fillStyle="darkblue";
bkCtx.rect(0,0,background.width,background.height);
bkCtx.fill();
bkCtx.beginPath();
for(var n=0;n<100;n++){
var x=parseInt(Math.random()*canvas.width);
var y=parseInt(Math.random()*canvas.height);
var radius=Math.random()*3;
bkCtx.arc(x,y,radius,0,Math.PI*2,false);
bkCtx.closePath();
}
bkCtx.fillStyle="white";
bkCtx.fill();
// create an new image using the starfield canvas
var img=document.createElement("img");
img.src=background.toDataURL();
现在,前面的画布用于所有游戏对象
您的游戏效率高,性能好,有2张画布专门用于他们自己的目的
下面是代码和小提琴:
正文{padding:20px;}
#容器{
位置:相对位置;
边框:1px纯蓝色;
宽度:300px;
高度:300px;
}
.副NVS{
位置:绝对位置;
}
$(函数(){
//保罗·爱尔兰的伟大英国皇家空军
window.requestAnimFrame=(函数(回调){
返回window.requestAnimationFrame | | | window.webkitRequestAnimationFrame | | | window.mozRequestAnimationFrame | | window.oRequestAnimationFrame | | window.msRequestAnimationFrame||
函数(回调){
设置超时(回调,1000/60);
};
})();
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
var background=document.getElementById(“背景”);
var bkCtx=background.getContext(“2d”);
//创建随机星星的图像
var backImage=RandomStarsImage();
//在前面的画布上画画
ctx.beginPath();
ctx.fillStyle=“红色”;
ctx.rect(75100100,50);
ctx.arc(175125,25,0,数学PI*2,假);
ctx.closePath();
ctx.fill();
//开始在背景画布上平移随机星星图像
var fps=60;
var offsetLeft=0;
潘斯塔();
函数panStars(){
//增加左偏移量
offsetLeft+=1;
如果(offsetLeft>backImage.width){offsetLeft=0;}
//绘制星域图像并再次绘制
//填充第一幅图像右侧的空白
clearRect(0,0,背景.宽度,背景.高度);
bkCtx.drawImage(背景图像,-offsetLeft,0);
bkCtx.drawImage(backImage,backImage.width offsetLeft,0);
setTimeout(函数(){
请求帧(panStars);
},1000/帧);
}
函数RandomStarsImage(){
//在画布上绘制一个随机星域
bkCtx.beginPath();
bkCtx.fillStyle=“暗蓝色”;
bkCtx.rect(0,0,背景.宽度,背景.高度);
bkCtx.fill();
bkCtx.beginPath();
对于(var n=0;您是否存在实际性能问题,或者这是关于过早优化的问题?嗨,markE。非常感谢您的完美解决方案。即使将宽度/高度加倍,动画在我的笔记本电脑上仍然非常流畅,干杯…:-)嗨,Mark,我将“代码”复制到“myDir/soStars.html”文件中。我制作了一个“myDir/css/reset.css”从复制内容(&M)。我双击了soStars.html并在WinXP sp3上的FF 21.0中启动。结果spaceship显示西斯白色背景,但没有星形字段。我在fireBug中设置了一个断点“bkCtx.clearRect(0,0,background.width,background.height);”结果星形字段显示。我重置断点并将其设置为“setTimeout(function(){”.结果无星场谢谢你的帮助-爱与和平Joe@JoeCodeswelluser601770:糟糕!我忘了添加Paul Irish的伟大requestAnimationFrame回退(由您的FF使用)。我已经更新了我的答案和提琴,所以它们现在应该可以为你工作了。谢谢提醒!javascript代码什么时候调用?这是我不确定的部分。@DougHauf.Hi--很高兴见到你。在网页上,你可以将脚本(例如javascript)放在里面,将javascript放在这里。标记。上面的代码也使用jQuery(一个消除不同浏览器制造商之间不一致的网页附加库)。下面的代码告诉浏览器首先等待所有标签元素加载到页面上,然后在$(function(){lotsofjavascript})内运行脚本;
我通常不推荐w3学校(他们有时有一些不准确的信息)但他们确实有相当好的教程:
<div id="container">
<canvas id="background" class="subcanvs" width=300; height=300;></canvas>
<canvas id="canvas" class="subcanvs" width=300; height=300;></canvas>
</div>
#container{
position:relative;
border:1px solid blue;
width:300px;
height:300px;
}
.subcanvs{
position:absolute;
}
var fps = 60;
var offsetLeft=0;
panStars();
function panStars() {
// increase the left offset
offsetLeft+=1;
if(offsetLeft>backImage.width){ offsetLeft=0; }
// draw the starfield image and
// draw it again to fill the empty space on the right of the first image
bkCtx.clearRect(0,0,background.width,background.height);
bkCtx.drawImage(backImage,-offsetLeft,0);
bkCtx.drawImage(backImage,backImage.width-offsetLeft,0);
setTimeout(function() {
requestAnimationFrame(panStars);
}, 1000 / fps);
}
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{padding:20px;}
#container{
position:relative;
border:1px solid blue;
width:300px;
height:300px;
}
.subcanvs{
position:absolute;
}
</style>
<script>
$(function(){
// Paul Irish's great RAF shim
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var background=document.getElementById("background");
var bkCtx=background.getContext("2d");
// create an image of random stars
var backImage=RandomStarsImage();
// draw on the front canvas
ctx.beginPath();
ctx.fillStyle="red";
ctx.rect(75,100,100,50);
ctx.arc(175,125,25,0,Math.PI*2,false);
ctx.closePath();
ctx.fill();
// start panning the random stars image across the background canvas
var fps = 60;
var offsetLeft=0;
panStars();
function panStars() {
// increase the left offset
offsetLeft+=1;
if(offsetLeft>backImage.width){ offsetLeft=0; }
// draw the starfield image and draw it again
// to fill the empty space on the right of the first image
bkCtx.clearRect(0,0,background.width,background.height);
bkCtx.drawImage(backImage,-offsetLeft,0);
bkCtx.drawImage(backImage,backImage.width-offsetLeft,0);
setTimeout(function() {
requestAnimFrame(panStars);
}, 1000 / fps);
}
function RandomStarsImage(){
// draw a random starfield on the canvas
bkCtx.beginPath();
bkCtx.fillStyle="darkblue";
bkCtx.rect(0,0,background.width,background.height);
bkCtx.fill();
bkCtx.beginPath();
for(var n=0;n<100;n++){
var x=parseInt(Math.random()*canvas.width);
var y=parseInt(Math.random()*canvas.height);
var radius=Math.random()*3;
bkCtx.arc(x,y,radius,0,Math.PI*2,false);
bkCtx.closePath();
}
bkCtx.fillStyle="white";
bkCtx.fill();
// create an new image using the starfield canvas
var img=document.createElement("img");
img.src=background.toDataURL();
return(img);
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container">
<canvas id="background" class="subcanvs" width=300; height=300;></canvas>
<canvas id="canvas" class="subcanvs" width=300; height=300;></canvas>
</div>
</body>
</html>