<canvas id="CycCanvas2" width="300" height="300"></canvas> <label><input type="range" min=1 max=99 value=50 id="fSlider" >比率</label> <label><input type="range" min=1 max=10 value=5 id="NSlider" >歯数N</label> <label><input type="range" min=1 max=10 value=5 id="MSlider" >歯数M</label> <script> /* サイクロイド曲線描画 原作:裏目小僧*/ var cvs = document.getElementById("CycCanvas2"); var c = cvs.getContext("2d"); var X0 =cvs.width/2; var Y0 =cvs.height/2; var rotc=0; var f =0.5; var N = 1+Math.trunc(Math.random() * 5); var fSlider = document.getElementById('fSlider'); fSlider.value = f*100; var NSlider = document.getElementById('NSlider') var MSlider = document.getElementById('MSlider') NSlider,value = N; MSlider,value = N; function cycDraw(n,x0,y0,r0,rot,f) {//一枚の歯車描画 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); c.beginPath(); for(let i = 0 ; i<psz ; i++){ let d0 = i*NN / r0; let d1 = d0 * n; d0 = d0 + rot; 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()で指定した始点に向けて線を引き、領域を閉じます。 c.fill(); //stroke()では輪郭線を描き、fill()にすると中を塗りつぶします。 return ; }; let ra=0; let L; let M; let r0; let A=0; let B=0; let C=0;
clBac="#ffffff";
const QuDRAW = function(){ X0 =cvs.width/2; Y0 =cvs.height/2; f = Math.round(fSlider.value)/100; N = Math.round(NSlider.value); M= Math.round(MSlider.value); r0 =((Y0 - 4) / ((N + M) + f * 2))*0.8; c.fillStyle=clBac; c.fillRect(0, 0, cvs.width,cvs.height); let oM=(M&1)*Math.PI;//奇数の時反転させる let x1=B+X0-r0*N;//左上 let y1=C+Y0-r0*N; c.fillStyle="#0000AF"; cycDraw(N,x1,y1,r0,(-360*(1-f/2)-rotc) * Math.PI / 180/N,f);//N枚の歯車描画 L=r0*N+r0*M;//歯車の中心の距離 let x2=x1+L;//右上 let y2=y1; c.fillStyle="rgba(" + [32, 0, 16, 0.7] + ")";; cycDraw(M,x2,y2,r0,((360*(-f/2)+rotc) * Math.PI / 180+oM)/M ,1-f);//M枚の歯車描画 A=Math.round(A); let H=(Math.sqrt(L*L-A*A)); let x3=x1+A;//左下 A^2+ let y3=y1+H; ra=(Math.asin(A/L)-Math.PI/2)*(M+N); let q=2*Math.PI*(M-N)/(N); c.fillStyle="#502010"; cycDraw(M,x3,y3,r0,((360*(-f/2)+rotc) * Math.PI / 180+oM-ra)/M,1-f);//M枚の歯車 上と接続 let x4=x3+L;//右下 let y4=y3; c.fillStyle="rgba(" + [0, 0, 0, 0.3] + ")"; let oN=((N^M)&1)*Math.PI;//歯数が偶奇の時反転させる cycDraw(N,x4,y4,r0,((-360*(1-f/2)-rotc)* Math.PI / 180+ra+oN)/N,f);//N枚の歯車 左と接続 cycDraw(N,x4,y4,r0,((-360*(1-f/2)-rotc)* Math.PI / 180-ra+oN)/N,f);//N枚の歯車 上と接続 rotc+=5;//回転角を進めてゆく if(rotc>360) rotc-=360; }; let m = {T:false,On:false, x:0,y:0 }; function onTMoff(){clBac="#FFF";m.On=false;m.T=false; let def=Math.sin(ra); let C=Math.cos(ra); if(Math.abs(def)<0.3){ A=A-C*def*r0/2; QuDRAW(); } }
function onMouseDown(e){clBac="#ECF";m.T=true;m.On=true;m.x=e.offsetX;m.y=e.offsetY;} function onMouseMove(e){ if(m.T){ let x=e.offsetX-m.x; let y=e.offsetY-m.y; if(e.offsetY<Y0) {B+=x; A-=x;}else A+=x; C+=y; }; m.T=m.On; m.x=e.offsetX;m.y=e.offsetY; }; function onTMove(e){ e.preventDefault(); let r= e.target.getBoundingClientRect(); if(e.touches.length=1){ let sx=e.touches[0].pageX;//座標関係なく差分だけで動かす let sy=e.touches[0].pageY-r.top + window.pageYOffset; if(m.T){ let x=sx-m.x; let y=sy-m.y; if(sy<Y0) {B+=x; A-=x;}else A+=x; C+=y; }; m.T=true; m.x=sx;m.y=sy; }else m.T=false;//途中複数タッチになったら跳躍防止 }; var IntVal= setInterval(QuDRAW , 100); cvs.addEventListener('mousemove', onMouseMove); cvs.addEventListener('mousedown', onMouseDown); cvs.addEventListener('mouseup' , onTMoff); cvs.addEventListener('touchmove', onTMove); cvs.addEventListener('touchend' ,onTMoff); </script> <INPUT TYPE="BUTTON" VALUE="表示幅を4割増" onClick=cvs.width*=1.4142;cvs.height*=1.4142;></INPUT><BR>
プライバシーポリシー本文は日本語以外に翻訳禁止