会动的齿轮

会动的齿轮

先上效果

会动的齿轮
用js里面的canas实现的,实际效果齿轮会动,还是比较有意思的,再配点音乐,那就完美了。

问题解析

js里面的canas知识大家可以参看https://www.runoob.com/html/html5-canvas.html,我这里就不介绍了,通过图形我们可以看出我们有两类齿轮,一类是外圈橘黄色的,一类是里面蓝色的。

大齿轮解析

大齿轮外圈是个圆,直接用arc画就行了,现在的问题主要是内圈的实现,我们看个大一点齿的外圈图:
放大外圈图
针对一个齿来分析,建立坐标系,如下图:
内齿
可以看到D1ABCD可以构成一个最小单元的齿,我们只要将这个齿旋转进行循环旋转以后就可以得到外圈的内齿了,现在我们假定O圆心坐标为(x,y),内圆半径OT为r1,外圆半径OD1=r2,每个锯齿和锯齿间空隙对应的圆心角为w0,其中T是AB的中点,AT=BT=d,在这些条件下,容易得到下面的坐标:
x T = r 1 ∗ c o s ( w 0 / 2 ) + x x_T=r_1*cos(w_0/2)+x xT=r1cos(w0/2)+x
y T = r 1 ∗ s i n ( w 0 / 2 ) + y y_T=r_1*sin(w_0/2)+y yT=r1sin(w0/2)+y
则可以得到A,B坐标
x A = r 1 ∗ c o s ( w 0 / 2 ) + x + d ∗ s i n ( w 0 / 2 ) x_A=r_1*cos(w_0/2)+x+d*sin(w_0/2) xA=r1cos(w0/2)+x+dsin(w0/2)
y A = r 1 ∗ s i n ( w 0 / 2 ) + y − d ∗ c o s ( w 0 / 2 ) y_A=r_1*sin(w_0/2)+y-d*cos(w_0/2) yA=r1sin(w0/2)+ydcos(w0/2)

x B = r 1 ∗ c o s ( w 0 / 2 ) + x − d ∗ s i n ( w 0 / 2 ) x_B=r_1*cos(w_0/2)+x-d*sin(w_0/2) xB=r1cos(w0/2)+xdsin(w0/2)
y B = r 1 ∗ s i n ( w 0 / 2 ) + y + d ∗ c o s ( w 0 / 2 ) y_B=r_1*sin(w_0/2)+y+d*cos(w_0/2) yB=r1sin(w0/2)+y+dcos(w0/2)
C点和D点都在外圆上,因此坐标为:
x C = r 2 ∗ c o s ( w 0 ) + x x_C=r_2*cos(w_0)+x xC=r2cos(w0)+x
y C = r 2 ∗ s i n ( w 0 ) + y y_C=r_2*sin(w_0)+y yC=r2sin(w0)+y
x D = r 2 ∗ c o s ( 2 ∗ w 0 ) + x x_D=r_2*cos(2*w_0)+x xD=r2cos(2w0)+x
y D = r 2 ∗ s i n ( 2 ∗ w 0 ) + y y_D=r_2*sin(2*w_0)+y yD=r2sin(2w0)+y
思考为了使这个齿轮转动起来,那没初始角就不一定是0了,即D1不在坐标轴上,还有一个夹角,上面的坐标只需要把里面的角都加上初始角w0就可以了,按照这个思路用js实现代码如下:

function gear1(ctx,x,y,r1,r2,n,d,p0){
         /*
         ctx:用于画图的对象
         x,y:圆心的坐标
         r1:齿轮内元半径
         r2:齿轮外圆半径
         n:齿轮及间隔平分数量
         d:齿的凸起的半距离
         p0:初始角度
         */
         
         var x0=x+r2;
         var y0=y;
         //每个齿对应的圆心角
         var w0=2*Math.PI/n;
         var w1=p0;
         var w2=w0/2;
         
         var rw=10;
         ctx.beginPath();
         ctx.arc(x,y,r2+10,0,2*Math.PI);
         ctx.fillStyle="#ff7f50";
         ctx.fill();
         ctx.stroke();
         
         ctx.beginPath();
         ctx.arc(x,y,rw,0,2*Math.PI);
         ctx.stroke();
         
         ctx.beginPath();
         //移动至初始位置
         var Ax=r2*Math.cos(w1)+x;
	     var Ay=r2*Math.sin(w1)+y;
	     ctx.moveTo(Ax,Ay);
 
         for(var i=0;i<n/2;i++){
             w2=w1+w0/2;//初始夹角
             //A点坐标   
	     var Ax=r1*Math.cos(w2)+d*Math.sin(w2)+x;
	     var Ay=r1*Math.sin(w2)-d*Math.cos(w2)+y;
	     //B点坐标
	     var Bx=r1*Math.cos(w2)-d*Math.sin(w2)+x;
	     var By=r1*Math.sin(w2)+d*Math.cos(w2)+y;
	     //C点坐标   
	     var w1=w1+w0;
	     var Cx=r2*Math.cos(w1)+x;
	     var Cy=r2*Math.sin(w1)+y;
	     //D点坐标    
	     var w1=w1+w0;
	     var Dx=r2*Math.cos(w1)+x;
	     var Dy=r2*Math.sin(w1)+y;
	          
	     //连线   
	     ctx.lineTo(Ax,Ay);
	     ctx.lineTo(Bx,By);
	     ctx.lineTo(Cx,Cy);
	     ctx.lineTo(Dx,Dy);  
         
         }
         
         ctx.stroke();
         ctx.fillStyle="#ffffff";
         ctx.fill();
           
      }

小齿轮解析

小齿轮和大齿轮类似,不过小齿轮的齿是向外凸的,所以建立坐标系分析如下:
小齿轮坐标
可以看到D1ABCD可以构成一个最小单元的齿,我们只要将这个齿旋转进行循环旋转以后就可以得到外圈的内齿了,现在我们假定O圆心坐标为(x,y),内圆半径OD1为r1,外圆半径OT=r2,每个锯齿和锯齿间空隙对应的圆心角为w0,其中T是AB的中点,AT=BT=d,在这些条件下,容易得到下面的坐标:
x T = r 2 ∗ c o s ( w 0 / 2 ) + x x_T=r_2*cos(w_0/2)+x xT=r2cos(w0/2)+x
y T = r 2 ∗ s i n ( w 0 / 2 ) + y y_T=r_2*sin(w_0/2)+y yT=r2sin(w0/2)+y
则可以得到A,B坐标
x A = r 2 ∗ c o s ( w 0 / 2 ) + x + d ∗ s i n ( w 0 / 2 ) x_A=r_2*cos(w_0/2)+x+d*sin(w_0/2) xA=r2cos(w0/2)+x+dsin(w0/2)
y A = r 2 ∗ s i n ( w 0 / 2 ) + y − d ∗ c o s ( w 0 / 2 ) y_A=r_2*sin(w_0/2)+y-d*cos(w_0/2) yA=r2sin(w0/2)+ydcos(w0/2)

x B = r 2 ∗ c o s ( w 0 / 2 ) + x − d ∗ s i n ( w 0 / 2 ) x_B=r_2*cos(w_0/2)+x-d*sin(w_0/2) xB=r2cos(w0/2)+xdsin(w0/2)
y B = r 2 ∗ s i n ( w 0 / 2 ) + y + d ∗ c o s ( w 0 / 2 ) y_B=r_2*sin(w_0/2)+y+d*cos(w_0/2) yB=r2sin(w0/2)+y+dcos(w0/2)
C点和D点都在外圆上,因此坐标为:
x C = r 1 ∗ c o s ( w 0 ) + x x_C=r_1*cos(w_0)+x xC=r1cos(w0)+x
y C = r 1 ∗ s i n ( w 0 ) + y y_C=r_1*sin(w_0)+y yC=r1sin(w0)+y
x D = r 1 ∗ c o s ( 2 ∗ w 0 ) + x x_D=r_1*cos(2*w_0)+x xD=r1cos(2w0)+x
y D = r 1 ∗ s i n ( 2 ∗ w 0 ) + y y_D=r_1*sin(2*w_0)+y yD=r1sin(2w0)+y
思考为了使这个齿轮转动起来,那没初始角就不一定是0了,即D1不在坐标轴上,还有一个夹角,上面的坐标只需要把里面的角都加上初始角w0就可以了,按照这个思路用js实现代码如下:

function gear(ctx,x,y,r1,r2,n,d,p0){
	      /*
         ctx:用于画图的对象
         x,y:圆心的坐标
         r1:齿轮内元半径
         r2:齿轮外圆半径
         n:齿轮及间隔平分数量
         d:齿的凸起的半距离
         p0:初始角度
         */
         
         var x0=x+r2;
         var y0=y;
       
         var w0=2*Math.PI/n;
         
         var w1=p0;
         var w2=w0/2;
         
         var rw=10;
         
         ctx.beginPath();
		 //移动至初始位置D1
         var D1x=r1*Math.cos(w1)+x;
	     var D1y=r1*Math.sin(w1)+y;
	     
	     ctx.moveTo(D1x,D1y);
     
         for(var i=0;i<n/2;i++){
             w2=w1+w0/2;
             //A点坐标			 
	         var Ax=r2*Math.cos(w2)+d*Math.sin(w2)+x;
	         var Ay=r2*Math.sin(w2)-d*Math.cos(w2)+y;
	         //B点坐标	
	         var Bx=r2*Math.cos(w2)-d*Math.sin(w2)+x;
	         var By=r2*Math.sin(w2)+d*Math.cos(w2)+y;
	         
	         var w1=w1+w0;
			 //C点坐标	
	         var Cx=r1*Math.cos(w1)+x;
	         var Cy=r1*Math.sin(w1)+y;
	         
	         var w1=w1+w0;
			 //D点坐标	
	         var Dx=r1*Math.cos(w1)+x;
	         var Dy=r1*Math.sin(w1)+y;
	          
	         //连线
	         ctx.lineTo(Ax,Ay);
	         ctx.lineTo(Bx,By);
	         ctx.lineTo(Cx,Cy);
	         ctx.lineTo(Dx,Dy);  
         
         }
         
         ctx.stroke();
         ctx.fillStyle="#00BFFF";
         ctx.closePath();
         ctx.fill();
         
         ctx.beginPath();
         ctx.fillStyle="#808080";
         ctx.arc(x,y,rw,0,2*Math.PI);//内部小圆
         ctx.closePath();
         ctx.fill(); 
      }

齿轮位置

可以看出圆心的位置构成一个等边三角形,因此我们可以画出下面坐标:
圆心位置坐标
假设A坐标为(x,y),该等边三角形边长为a,则我们容易求出其他几个点坐标:
x B = x + a x_B=x+a xB=x+a
y B = y y_B=y yB=y
x C = x + a 2 x_C=x+\frac{a}{2} xC=x+2a
y C = y + a ∗ s i n ( π 3 ) y_C=y+a*sin(\frac{π}{3}) yC=y+asin(3π)
x D = x + a 2 x_D=x+\frac{a}{2} xD=x+2a
y D = y + a 2 ∗ t a n ( π 6 ) y_D=y+\frac{a}{2}*tan(\frac{π}{6}) yD=y+2atan(6π)

由此我们可以形成这段代码:

  function load(){
          n=0;

          setInterval(function(){
		          var c=document.getElementById("mycanvas");
			      var ctx=c.getContext("2d");
			      ctx.fillStyle="#00BFFF";
			      ctx.clearRect(0,0,c.width,c.height);
			  
			      var bl=200;
			      var x1=200;//A点坐标
			      var y1=200;
			      
			      var x2=x1+bl;//B点坐标
			      var y2=y1;
			      
			      var x3=x1+bl*Math.cos(Math.PI/3);//C点坐标
			      var y3=y1+bl*Math.sin(Math.PI/3);
			      
			      var x4=x1+bl*Math.cos(Math.PI/3);//D点坐标
			      var y4=y1+Math.tan(Math.PI/6)*bl/2;
			         
			      p0=2*Math.PI/64*n;
			      p1=-p0/2;
			      p2=-p0/5+2*Math.PI/32*2;
			      gear1(ctx,x3,y4,185,195,80,5,p2);
			      gear(ctx,x1,y1,70,80,32,5,p1);
			      gear(ctx,x2,y2,70,80,32,5,p1);
			      gear(ctx,x3,y3,70,80,32,5,p1);
			      gear(ctx,x3,y4,35,45,16,5,p0);
				  
                  n++;
				  if(n==64){
                      n=0;
                   }
               
          },20);
		  }

解释下齿数与角度的关系,外圈40齿(80份),内部相同的三个都是16齿(32份),中心齿轮是8齿(16份),因此齿数比是5:2:1,齿数多的转速就慢,因此他们的角速度比应该是:1:2:5,当然初始角度需要根据实际情况做一个调整,让齿轮能啮合在一起,最后把整体代码贴出来:

<!DOCTYPE HTML>
<html>
  <head>
  
    <title>ta</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
  </head>
  
  <script type="text/javascript">
  function load(){
          n=0;

          setInterval(function(){
		          var c=document.getElementById("mycanvas");
			      var ctx=c.getContext("2d");
			      ctx.fillStyle="#00BFFF";
			      ctx.clearRect(0,0,c.width,c.height);
			  
			      var bl=200;
			      var x1=200;//A点坐标
			      var y1=200;
			      
			      var x2=x1+bl;//B点坐标
			      var y2=y1;
			      
			      var x3=x1+bl*Math.cos(Math.PI/3);//C点坐标
			      var y3=y1+bl*Math.sin(Math.PI/3);
			      
			      var x4=x1+bl*Math.cos(Math.PI/3);//D点坐标
			      var y4=y1+Math.tan(Math.PI/6)*bl/2;
			         
			      p0=2*Math.PI/64*n;
			      p1=-p0/2;
			      p2=-p0/5+2*Math.PI/32*2;
			      gear1(ctx,x3,y4,185,195,80,5,p2);
			      gear(ctx,x1,y1,70,80,32,5,p1);
			      gear(ctx,x2,y2,70,80,32,5,p1);
			      gear(ctx,x3,y3,70,80,32,5,p1);
			      gear(ctx,x3,y4,35,45,16,5,p0);
				  
                  n++;
				  if(n==64){
                      n=0;
                   }
               
          },20);
		  }
      
      function gear(ctx,x,y,r1,r2,n,d,p0){
	      /*
         ctx:用于画图的对象
         x,y:圆心的坐标
         r1:齿轮内元半径
         r2:齿轮外圆半径
         n:齿轮及间隔平分数量
         d:齿的凸起的半距离
         p0:初始角度
         */
         
         var x0=x+r2;
         var y0=y;
       
         var w0=2*Math.PI/n;
         
         var w1=p0;
         var w2=w0/2;
         
         var rw=10;
         
         ctx.beginPath();
		 //移动至初始位置D1
         var D1x=r1*Math.cos(w1)+x;
	     var D1y=r1*Math.sin(w1)+y;
	     
	     ctx.moveTo(D1x,D1y);
     
         for(var i=0;i<n/2;i++){
             w2=w1+w0/2;
             //A点坐标			 
	         var Ax=r2*Math.cos(w2)+d*Math.sin(w2)+x;
	         var Ay=r2*Math.sin(w2)-d*Math.cos(w2)+y;
	         //B点坐标	
	         var Bx=r2*Math.cos(w2)-d*Math.sin(w2)+x;
	         var By=r2*Math.sin(w2)+d*Math.cos(w2)+y;
	         
	         var w1=w1+w0;
			 //C点坐标	
	         var Cx=r1*Math.cos(w1)+x;
	         var Cy=r1*Math.sin(w1)+y;
	         
	         var w1=w1+w0;
			 //D点坐标	
	         var Dx=r1*Math.cos(w1)+x;
	         var Dy=r1*Math.sin(w1)+y;
	          
	         //连线
	         ctx.lineTo(Ax,Ay);
	         ctx.lineTo(Bx,By);
	         ctx.lineTo(Cx,Cy);
	         ctx.lineTo(Dx,Dy);  
         
         }
         
         ctx.stroke();
         ctx.fillStyle="#00BFFF";
         ctx.closePath();
         ctx.fill();
         
         ctx.beginPath();
         ctx.fillStyle="#808080";
         ctx.arc(x,y,rw,0,2*Math.PI);//内部小圆
         ctx.closePath();
         ctx.fill(); 
      }
      
       function gear1(ctx,x,y,r1,r2,n,d,p0){
         /*
         ctx:用于画图的对象
         x,y:圆心的坐标
         r1:齿轮内元半径
         r2:齿轮外圆半径
         n:齿轮及间隔平分数量
         d:齿的凸起的半距离
         p0:初始角度
         */
         
         var x0=x+r2;
         var y0=y;
         //每个齿对应的圆心角
         var w0=2*Math.PI/n;
         
         var w1=p0;
         var w2=w0/2;
         
        
         
         var rw=10;
         ctx.beginPath();
         ctx.arc(x,y,r2+10,0,2*Math.PI);
         ctx.fillStyle="#ff7f50";
         ctx.fill();
         ctx.stroke();
         
         ctx.beginPath();
         ctx.arc(x,y,rw,0,2*Math.PI);
         ctx.stroke();
         
         ctx.beginPath();
         //移动至初始位置
         var D1x=r2*Math.cos(w1)+x;
	     var D1y=r2*Math.sin(w1)+y;
	     
	     ctx.moveTo(D1x,D1y);
     
         for(var i=0;i<n/2;i++){
             w2=w1+w0/2;//初始夹角
             //A点坐标   
	     var Ax=r1*Math.cos(w2)+d*Math.sin(w2)+x;
	     var Ay=r1*Math.sin(w2)-d*Math.cos(w2)+y;
	     //B点坐标
	     var Bx=r1*Math.cos(w2)-d*Math.sin(w2)+x;
	     var By=r1*Math.sin(w2)+d*Math.cos(w2)+y;
	     //C点坐标   
	     var w1=w1+w0;
	     var Cx=r2*Math.cos(w1)+x;
	     var Cy=r2*Math.sin(w1)+y;
	     //D点坐标    
	     var w1=w1+w0;
	     var Dx=r2*Math.cos(w1)+x;
	     var Dy=r2*Math.sin(w1)+y;
	          
	     //连线   
	     ctx.lineTo(Ax,Ay);
	     ctx.lineTo(Bx,By);
	     ctx.lineTo(Cx,Cy);
	     ctx.lineTo(Dx,Dy);  
         
         }
         
         ctx.stroke();
         ctx.fillStyle="#ffffff";
         ctx.fill();
         
         
      
      }
        
  </script>
  
  
  <body onload="load()">

       <canvas id="mycanvas" width="800" height="800"></canvas>
       
    
  </body>
</html>
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值