zoukankan      html  css  js  c++  java
  • canvas小球动画原理

    随着html5发展,canvas标签作为h5革命性的发展标志也越来越流行。canvas标签的强大之处,不仅在于它可以作为一个独立的画布,也可以利用canvas做一些动画而不用导入flash文件。同时,canvas还可以一些游戏、商城商品图片放大器功能等等。

    这篇博客先写一些简单动画,同时描述一下原理。

    首先,canvas标签不是一个独立的部分,它是要以js代码辅助而成的一个模块,所以js代码对其尤为重要。

    body中写入canvas标签:

    <canvas id="canvas" width="750" height="500"></canvas>
    <input type="button"  id="animatebutton" value="animate" /> //控制小球的运动与暂停

      

    直接上js代码:

    canvas的js开头都是固定的:

    var canvas = document.getElementById('canvas'),
    cx= canvas.getContext('2d'),
    paused = true ,//设置小球加载完成是否暂停,现在加载完成小球不动。

    加载三个小球的数据:

    discs = [
    		{
    			x:150,
    			y:250,
    			velocityx:-3.2,      //小球横向运动速度
    			velocityy:3.5,       //小球纵向运动速度
    			radius:25,        //小球半径
    			strokestyle:'gray',     //小球填充颜色
    		},
    		{
    			x:50,
    			y:150,
    			velocityx:2.2,
    			velocityy:2.5,
    			radius:25,
    			strokestyle:'blue',
    		},
    		{
    			x:150,
    			y:75,
    			velocityx:1.2,
    			velocityy:1.5,
    			radius:25,
    			strokestyle:'orange',
    		},
    		],
    

      

    定义小球的数量以及找到控制小球暂停的button

    numdiscs = discs.length, //小球数量
    animatebutton = document.getElementById('animatebutton');
    // 小球暂停开始按钮
    

     

    用canvas画出小球:

    function draw(){
    		var disc = discs[i];    //小球的索引
    		for(var i=0;i<numdiscs;i++)
    		{
    			disc = discs[i];
    			cx.save();                   
    			cx.beginPath();
    			cx.arc(disc.x,disc.y,disc.radius,0, Math.PI*2,false);
    			cx.fillStyle=disc.strokestyle;    //小球填充色
    			cx.fill();
    			cx.restore();
    			}
    		}
    

      

    设置碰撞及小球运动函数:

    function update(){
    		var disc = null;
    		for(var i=0;i<numdiscs;i++)
    		{
    			disc = discs[i];
    			if(disc.x +disc.velocityx+disc.radius > cx.canvas.width || disc.x + disc.velocityx -disc.radius<0)      //小球横向撞墙后朝相反方向运动
    			disc.velocityx = -disc.velocityx;
    			if(disc.y +disc.velocityy+disc.radius > cx.canvas.height || disc.y + disc.velocityy -disc.radius<0)   //小球纵向向撞墙后朝相反方向运动
    			disc.velocityy = -disc.velocityy;
    			disc.x+=disc.velocityx;    //每次循环小球横向运动距离
    			disc.y+=disc.velocityy;  //每次循环小球纵向运动距离
    } }

     

    设置小球的运动,这是一个循环函数,当按钮点击运动的时候,小球每隔一点时间循环运动,其中

    window.requestAnimationFrame()函数是canvas标签中特有的,这个函数可以根据最佳流畅性自动选择循环一次的时间。
    function animate(){
    		if(!paused){
    		cx.clearRect(0,0,canvas.width,canvas.height);
    		update();
    		draw();
    		window.requestAnimationFrame(animate);
    			}
    		}
    

      

    运行以上函数:

    animatebutton.onclick = function (){               
    		paused = paused? false:true;
    		if(paused){                        //点击按钮后,按钮文字改变
    		animatebutton.value = "animate";		
    		}
    		else{
    			window.requestAnimationFrame(animate);
    			animatebutton.value = "pause";      //点击按钮后,按钮文字改变
    			}
    		}
    

      

     

    代码整合:

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    	</head>
    	<body>
    		
    	<input type="button"  id="animatebutton" value="animate" />
    	<canvas id="canvas" width="750" height="500"></canvas>
    	</body>
    	<script type="text/javascript">
    		var canvas = document.getElementById('canvas'),
    		cx= canvas.getContext('2d'),
    		paused = true ,
    		discs = [
    		{
    			x:150,
    			y:250,
    			velocityx:-3.2,
    			velocityy:3.5,
    			radius:25,
    			strokestyle:'gray',
    		},
    		{
    			x:50,
    			y:150,
    			velocityx:2.2,
    			velocityy:2.5,
    			radius:25,
    			strokestyle:'blue',
    		},
    		{
    			x:150,
    			y:75,
    			velocityx:1.2,
    			velocityy:1.5,
    			radius:25,
    			strokestyle:'orange',
    		},
    		],
    
    		numdiscs = discs.length,
    		animatebutton = document.getElementById('animatebutton');
    		
    		function update(){
    			var disc = null;
    			for(var i=0;i<numdiscs;i++)
    			{
    				disc = discs[i];
    				if(disc.x +disc.velocityx+disc.radius > cx.canvas.width || disc.x + disc.velocityx -disc.radius<0)
    				disc.velocityx = -disc.velocityx;
    				if(disc.y +disc.velocityy+disc.radius > cx.canvas.height || disc.y + disc.velocityy -disc.radius<0)
    				disc.velocityy = -disc.velocityy;
    				disc.x+=disc.velocityx;
    				disc.y+=disc.velocityy;
    			}
    		}
    		
    		function draw(){
    			var disc = discs[i];
    			for(var i=0;i<numdiscs;i++)
    			{
    				disc = discs[i];
    				
    				cx.save();
    				cx.beginPath();
    				cx.arc(disc.x,disc.y,disc.radius,0, Math.PI*2,false);
    				cx.fillStyle=disc.strokestyle;
    				cx.fill();
    				//cx.stroke();
    				cx.restore();
    			}
    		}
    		function animate(){
    			if(!paused){
    				cx.clearRect(0,0,canvas.width,canvas.height);
    				
    				update();
    				draw();
    				window.requestAnimationFrame(animate);
    			}
    		}
    		
    		animatebutton.onclick = function (){
    			paused = paused? false:true;
    			if(paused){
    				animatebutton.value = "animate";
    				
    			}
    			else{
    				window.requestAnimationFrame(animate);
    				animatebutton.value = "pause";
    			}
    		}
    	</script>
    </html>
    

      

    效果:

    没有点击运动前:

    点击运动后:

    小球是一直运动的,点击pause之后,小球运动暂停。

  • 相关阅读:
    经典代码JSKeyword查看(M。。。$)的哦!
    django处理websocket
    产品所有者也应该是Scrum教练吗?
    google的javascript编码规范
    python 处理websocket
    [转] 虚拟座谈会:TDD有多美?
    python 数字相关
    google的python编码规范
    python 函数相关
    python推荐的模块结构
  • 原文地址:https://www.cnblogs.com/cyrfr/p/6520113.html