裏目小僧の部屋

JSサイクロイド曲線

<label><input type="range" min=1 max=99 value=50 id="fSlider" >比率</label>
<label><input type="range" min=1 max=10 value=2  id="NSlider" >歯数</label>
<canvas id="CycCanvas1" width="300" height="300"></canvas>
<script>
/* サイクロイドポンプ曲線描画  原作:裏目小僧*/
var cvs = document.getElementById("CycCanvas1");
var c = cvs.getContext("2d");
var X0 =150;
var Y0 =150;
var rotc=0;
var rad0=0;
var f =(1+Math.trunc(Math.random() * 18))/20;
var N = 3;//1+Math.trunc(Math.random() * 5);
let fSlider = document.getElementById('fSlider');
    fSlider.value = f*100;
let NSlider= document.getElementById('NSlider');
    NSlider.value = N;
function cycDraw(n,x0,y0,r0,rot) {//一枚の歯車描画
let  NN=2;//分解能大きくするほど荒い
let  r1 = r0  * f;       //外転
let  r2 = r0  * (1 - f); //内転
r0 = r0*n;
let  lap = 2 * Math.PI * r0; //円周
let  psz = Math.trunc(lap/NN);
rot=rot/n;
c.beginPath();
for(let i = 0 ; i<psz ; i++){
 let d0 = i*NN / r0;
 let d1 = d0 * n;
     d0 = d0 + rot+rad0/n;
  while( d1 > 2 * Math.PI)  d1 = d1 - 2 * Math.PI;
  if ( d1 / (2 * Math.PI) <= f ){ //外転描画
    d2 = d0 + d1 / f;
    x1 = x0 + Math.cos(d0) * (r0 + r1) - Math.cos(d2) * (r1);
    y1 = y0 + Math.sin(d0) * (r0 + r1) - Math.sin(d2) * (r1);
  } else { //内転
    d2 = d0 - (d1 - 2 * Math.PI * f) / (1 - f);
    x1 = x0 + Math.cos(d0) * (r0 - r2) + Math.cos(d2) * (r2);
    y1 = y0 + Math.sin(d0) * (r0 - r2) + Math.sin(d2) * (r2);
  };
  if(i == 0) c.moveTo(x1, y1);
  else c.lineTo(x1, y1);
};
c.closePath();  //moveTo()で指定した始点に向けて線を引き、領域を閉じます。
return ;
};
const WDRAW = function(){
let ra=rad0;
 f = Math.round(fSlider.value)/100;
 N = Math.round(NSlider.value);
let r0 =((Y0 - 4) / ((N + 1) + f * 2));
c.fillStyle="#444444";
c.arc(X0,Y0,r0*(N+1+2*f),0,2*Math.PI);
c.fill();
c.fillStyle="#FFFF00";
cycDraw(N+1,X0,Y0,r0,rotc  * Math.PI / 180);//N+1枚の歯車描画
c.fill();  //stroke()では輪郭線を描き、fill()にすると中を塗りつぶします。
c.fillStyle="#000000";
cycDraw(N,X0+r0*Math.cos(ra),Y0+r0*Math.sin(ra),r0,rotc  * Math.PI / 180-ra);//N枚の歯車描画
c.fill();  //stroke()では輪郭線を描き、fill()にすると中を塗りつぶします。
rotc+=3;//回転角を進めてゆく
if(rotc>360) rotc-=360;
};
const RDRAW = function(){//外側を固定し内側を回転
 f = Math.round(fSlider.value)/100;
 N = Math.round(NSlider.value);
let r0 =((Y0 - 4) / ((N + 1) + f * 2));
c.fillStyle="#444444";
c.arc(X0,Y0,r0*(N+1+2*f),0,2*Math.PI);
c.fill();
c.fillStyle="#FFFF00";

cycDraw(N+1,X0,Y0,r0,0);//N+1枚の歯車描画
 c.fill();  //stroke()では輪郭線を描き、fill()にすると中を塗りつぶします。
 let   rad = rotc  * Math.PI / 180;
 let   x1 = X0 + (r0 * Math.cos(rad));
 let   y1 = Y0 + (r0 * Math.sin(rad));
 c.fillStyle="#000000";
 cycDraw(N,x1,y1,r0,-rad);//N枚の歯車描画
 c.fill();  //stroke()では輪郭線を描き、fill()にすると中を塗りつぶします。
 rotc+=3;//回転角を進めてゆく
 if(rotc>360) rotc-=360;
};
const VDRAW = function(){//内側の回転振動
 f = Math.round(fSlider.value)/100;
 N = Math.round(NSlider.value);
let r0 =((Y0 - 4) / ((N + 1) + f * 2));
c.fillStyle="#444444";
c.arc(X0,Y0,3+r0*(N+1+2*f),0,2*Math.PI);
c.fill();
c.fillStyle="#FFFF00";
let   rad  = rotc  * Math.PI / 180;

cycDraw(N+1,X0,Y0,r0,rad);//N+1枚の歯車描画
c.fill();
let   x1 = X0 + (r0 * Math.cos(rad));
let   y1 = Y0 + (r0 * Math.sin(rad));
c.fillStyle="#000000";
cycDraw(N,x1,y1,r0,0);//N枚の歯車描画
c.fill();
rotc+=3;//回転角を進めてゆく
if(rotc>360) rotc-=360;
};
const VEDRAW = function(){//外側の回転振動
 f = Math.round(fSlider.value)/100;
 N = Math.round(NSlider.value);
let r0 =((Y0 - 4) / ((N + 2) + f * 2));
let   rad  = rotc  * Math.PI / 180;
let   x1 = X0 - (r0 * Math.cos(rad));
let   y1 = Y0 + (r0 * Math.sin(rad));
 c.fillStyle="#ffffff";
 c.fillRect(0, 0, cvs.width,cvs.height);
 c.fillStyle="#00ff00";
 c.beginPath();
 c.arc(X0,Y0,3+r0*(N+2+2*f),0,2*Math.PI);
 c.closePath();
 c.stroke();
 c.fillStyle="#444444";
 c.beginPath();
 c.arc(x1,y1,3+r0*(N+1+2*f),0,2*Math.PI);
 c.closePath();
 c.fill();
 c.fillStyle="#FFFF00";
 cycDraw(N+1,x1,y1,r0,0);//N+1枚の歯車描画
 c.fill();  //stroke()では輪郭線を描き、fill()にすると中を塗りつぶします。
 c.fillStyle="#000000";
 cycDraw(N,X0,Y0,r0,rad);//N枚の歯車描画
 c.fill();  //stroke()では輪郭線を描き、fill()にすると中を塗りつぶします。
 rotc+=3;//回転角を進めてゆく
 if(rotc>360) rotc-=360;
};
var rotp=0;
var rotSw=false;
function RotPad(onoff,x,y)
{
let  r=Math.atan2(X0-x,Y0-y);
if(rotSw)   rad0 -=  r-rotp;
  rotp=r;
  rotSw=onoff; 
}
cvs.addEventListener('mousemove', function(e){  RotPad(e.buttons>0, e.offsetX, e.offsetY); });
cvs.addEventListener('touchmove',function(e){
 e.preventDefault();
 let r= e.target.getBoundingClientRect();
 if(e.touches.length=1){
  let x=e.touches[0].pageX-r.left - window.pageXOffset;
  let y=e.touches[0].pageY-r.top - window.pageYOffset;
  RotPad(true,x,y);
  };
});
  cvs.addEventListener('touchend'   ,function(){rotSw=false;}); 

var IntVal= setInterval(WDRAW , 100);
</script>
 <INPUT TYPE="BUTTON" VALUE="外側を固定し内側を回転" onClick="clearInterval(IntVal);IntVal=setInterval(RDRAW , 100);"></INPUT>
  <INPUT TYPE="BUTTON" VALUE="外も内側も歯車のように回転" onClick="clearInterval(IntVal);IntVal=setInterval(WDRAW , 100);"></INPUT>
  <INPUT TYPE="BUTTON" VALUE="内側が回転振動" onClick="clearInterval(IntVal);IntVal=setInterval(VDRAW , 100);"></INPUT>
  <INPUT TYPE="BUTTON" VALUE="外側が回転振動" onClick="clearInterval(IntVal);IntVal=setInterval(VEDRAW , 100);"></INPUT>
 <INPUT TYPE="BUTTON" VALUE="表示幅を4割増" onClick="cvs.width*=1.4142;cvs.height*=1.4142;  X0 =cvs.width/2; Y0 =cvs.height/2; "></INPUT>


プライバシーポリシー本文は日本語以外に翻訳禁止