//================= Canvas elements let staticLayer = document.getElementById('static'); staticLayer.width = window.innerWidth; staticLayer.height = window.innerHeight; let beamLineLayer = document.getElementById('beamLine'); let colors = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]; let colorIndex = 0; function rotate(xy, center, rad){ let haha = [xy[0]-center[0], xy[1]-center[1]]; let kaka = [ haha[0]*Math.cos(rad) - haha[1]*Math.sin(rad), haha[0]*Math.sin(rad) + haha[1]*Math.cos(rad)]; return [ kaka[0] + center[0], kaka[1] + center[1]]; } function translate(xy, t){ return [xy[0] + t[0], xy[1] + t[1]]; } function distance(xy1, xy2){ return Math.sqrt( Math.pow(xy1[0]-xy2[0],2) + Math.pow(xy1[1]-xy2[1],2)); } class basicShape{ constructor(layer){ this.layer = layer; this.shape = new Path2D(); this.entracePos = [0,0]; this.exitPos = [0,0]; } clear(){ let ctx = this.layer.getContext('2d'); ctx.save(); ctx.globalCompositeOperation = 'destination-out'; ctx.fill(this.shape); ctx.stroke(this.shape); ctx.restore(); } } class tandemClass extends basicShape{ constructor(xy, l, w){ super(staticLayer); this.exitPos = [ xy[0], xy[1] - w - l]; this.shape.rect(xy[0] - w/2, xy[1] - l - w/2, w, l); this.shape.arc(xy[0], xy[1]-w/2, w/2, 0, Math.PI); this.shape.arc(xy[0], xy[1]-w/2 - l, w/2, Math.PI, 2* Math.PI); } draw(color){ let ctx = this.layer.getContext('2d'); ctx.fillStyle = color; ctx.fill(this.shape); } } class beamLine extends basicShape{ constructor(xy, rad, l){ super(beamLineLayer); this.offset = 0; this.lineWidth = 10; this.exitPos = [xy[0] + l, xy[1]]; this.exitPos = rotate(this.exitPos, xy, rad); this.shape.moveTo(xy[0], xy[1]); this.shape.lineTo(this.exitPos[0], this.exitPos[1]); } draw(color){ this.clear(); let ctx = this.layer.getContext('2d'); ctx.setLineDash([10,6]); ctx.lineDashOffset = -this.offset; ctx.lineWidth = 10; ctx.strokeStyle = color; ctx.stroke(this.shape); } march(color){ this.offset++; if( this.offset > 16) this.offset = 0; this.draw(color); //setTimeout(this.march.bind(this), 20); } } class beamRectElement extends basicShape{ constructor(xy, rad, l, w){ super(staticLayer); let A = [xy[0]-w/2, xy[1]]; let B = [xy[0]+w/2, xy[1]]; let C = [xy[0]+w/2, xy[1] - l]; let D = [xy[0]-w/2, xy[1] - l]; A = rotate(A, xy, rad); B = rotate(B, xy, rad); C = rotate(C, xy, rad); D = rotate(D, xy, rad); this.shape.moveTo(A[0], A[1]); this.shape.lineTo(B[0], B[1]); this.shape.lineTo(C[0], C[1]); this.shape.lineTo(D[0], D[1]); this.shape.closePath(); this.exitPos = [xy[0], xy[1] - l] } draw(color){ let ctx = this.layer.getContext('2d'); ctx.fillStyle = color; ctx.fill(this.shape); } } class beamCircleElement extends basicShape{ constructor(xy, r, rad0, rad1){ super(staticLayer); this.shape.moveTo(xy[0], xy[1]); this.shape.arc(xy[0], xy[1], r, rad0, rad1); let rad = (rad0 + rad1)/2; let l = [r*Math.cos(rad), r*Math.sin(rad)]; this.exitPos = [xy[0] + l[0], xy[1] + l[1]]; // the middle of the arc } GetExitPos(frac){ let rad = rad0 + Math.abs(rad0 - rad1) * frac; let l = [r*Math.cos(rad), r*Math.sin(rad)]; return [xy[0] + l[0], xy[1] + l[1]]; } draw(color){ let ctx = this.layer.getContext('2d'); ctx.fillStyle = color; ctx.fill(this.shape); } } class BeamSpilter extends basicShape{ constructor(xy, r, rad){ super(staticLayer); this.entracePos = xy; this.r = r; let w = r; let l = r/2; let A = [xy[0]+w/2, xy[1] - l]; let B = [xy[0]+w/2, xy[1]]; let C = [xy[0]-w/2, xy[1]]; let D = [xy[0]-w/2, xy[1] - l]; A = rotate(A, xy, rad); B = rotate(B, xy, rad); C = rotate(C, xy, rad); D = rotate(D, xy, rad); this.shape.moveTo(A[0], A[1]); this.shape.lineTo(B[0], B[1]); this.shape.lineTo(C[0], C[1]); this.shape.lineTo(D[0], D[1]); this.rad0 = rad - Math.PI*3/4; this.rad1 = rad - Math.PI/4; this.shape.arc(xy[0], xy[1], r, this.rad0 , this.rad1); } GetExitPos(frac){ let rad = this.rad0 + Math.abs(this.rad0 - this.rad1) * frac; let l = [this.r*Math.cos(rad), this.r*Math.sin(rad)]; return translate(this.entracePos, l); } draw(color){ let ctx = this.layer.getContext('2d'); ctx.fillStyle = color; ctx.fill(this.shape); } } ///========================= Sand Box; let windowSize = [staticLayer.width, staticLayer.height]; let RFSource1 = new beamRectElement([windowSize[0]*0.9, windowSize[1]*0.8], 0, 40, 100); let RFSource2 = new beamRectElement(RFSource1.exitPos, 0, 40, 20); let s1 = new BeamSpilter(translate(RFSource2.exitPos, [0, -100]), 50, Math.PI); let b1S = new beamLine(RFSource2.exitPos, Math.PI *3/2, 200); let tandem = new tandemClass(b1S.exitPos, 100, 100); let b10 = new beamLine(tandem.exitPos, Math.PI *3/2, 100); b10.offset = 8; RFSource1.draw('Olivedrab'); RFSource2.draw('Olivedrab'); b1S.draw('red'); s1.draw('gold'); tandem.draw('#782F40'); b10.draw('red'); function lineMotion(){ b1S.march('red'); b10.march('red'); setTimeout(lineMotion, 20); } lineMotion();