let my={} function init(){let version='0.84' my.mode=getJSQueryVar('mode','par') my.dragging=false let w=360 let h=300 my.wd=w my.ht=h let s='' s+='
' s+='' s+='' s+='
' s+=wrap({cls:'copyrt',pos:'abs',style:'left:5px; bottom:3px'},`© 2022 Rod Pierce v${version}`) s+='
' docInsert(s) switch(my.mode){case 'par':my.typeDescr='parallel' break case 'perp':my.typeDescr='perpendicular' break default:} my.can=new Can('canPar',w,h,2) my.exerPts=[[50,-50],[50,25],[50,-5],[5,50],[50,-1],] my.exerPtNo=-1 my.startQ=true my.draggingQ=false let el=my.can.el let imgHome=document.domain=='localhost'?'/mathsisfun/images/style/':'/images/style/' el.style.cursor='url('+imgHome+'pencil.svg), crosshair' el.addEventListener('mousedown',onmouseDown,false) el.addEventListener('mousemove',onmouseMove,false) el.addEventListener('touchstart',ontouchstart,false) el.addEventListener('touchmove',ontouchmove,false) next()} function next(){my.exerPtNo=++my.exerPtNo%my.exerPts.length let midX=my.wd/2+Math.random()*50 let midY=my.ht/2+Math.random()*50 my.exerLn=new Line(new Pt(midX,midY),new Pt(midX+my.exerPts[my.exerPtNo][0],midY+my.exerPts[my.exerPtNo][1])) my.userLn=new Line(new Pt(0,0),new Pt(0,0)) my.startQ=true drawMe()} function goodQ(){let successQ=false if(my.userLn.getLength()>10){switch(my.mode){case 'par':if(my.userLn.isParallel(my.exerLn,0.06))successQ=true break case 'perp':if(my.userLn.isPerp(my.exerLn,0.06))successQ=true break default:}} return successQ} function drawBG(w,h){let g=my.can.g g.lineWidth=1 for(let i=0;i<10;i++){let xPix=i*60 g.beginPath() if(i%2){g.strokeStyle='rgba(0,0,2556,0.2)'}else{g.strokeStyle='rgba(0,0,255,0.2)'} g.moveTo(xPix,0) g.lineTo(xPix,h) g.stroke()} for(let i=0;i<6;i++){let yPix=i*60 g.beginPath() if(i%2){g.strokeStyle='rgba(0,0,255,0.2)'}else{g.strokeStyle='rgba(0,0,255,0.2)'} g.moveTo(0,yPix) g.lineTo(w,yPix) g.stroke()}} function ontouchstart(ev){let touch=ev.targetTouches[0] ev.clientX=touch.clientX ev.clientY=touch.clientY ev.touchQ=true onmouseDown(ev)} function ontouchmove(ev){let touch=ev.targetTouches[0] ev.clientX=touch.clientX ev.clientY=touch.clientY ev.touchQ=true onmouseMove(ev) ev.preventDefault()} function ontouchend(ev){let el=my.can.el el.addEventListener('touchstart',ontouchstart,false) window.removeEventListener('touchend',ontouchend,false) if(my.draggingQ){my.draggingQ=false checkSuccess()}} function onmouseDown(ev){let[mouseX,mouseY]=my.can.mousePos(ev) my.userLn.a.x=mouseX my.userLn.a.y=mouseY my.draggingQ=true if(ev.touchQ){}else{} let el=my.can.el if(ev.touchQ){el.removeEventListener('touchstart',ontouchstart,false) window.addEventListener('touchend',ontouchend,false)}else{el.removeEventListener('mousedown',onmouseDown,false) window.addEventListener('mouseup',onmouseUp,false)} if(ev.preventDefault){ev.preventDefault()} else if(ev.returnValue){ev.returnValue=false} return false} function onmouseUp(ev){let el=my.can.el el.addEventListener('mousedown',onmouseDown,false) window.removeEventListener('mouseup',onmouseUp,false) if(my.draggingQ){my.draggingQ=false checkSuccess()}} function onmouseMove(ev){let[mouseX,mouseY]=my.can.mousePos(ev) my.userLn.b.x=mouseX my.userLn.b.y=mouseY if(my.draggingQ){drawMe()}} function checkSuccess(){let g=my.can.g if(goodQ()){g.fillStyle='gold' g.font='bold 24px Arial' g.fillText('Yes, they are '+my.typeDescr+'!',my.wd/2,30) g.fillStyle='hsla(240,100%,70%,1)' g.font='16px Arial' g.fillText('Try more, or press Next',my.wd/2,50)}else{g.fillStyle='red' g.font='16px Arial' g.fillText('Ooops, not right. Try again.',my.wd/2,30)}} function drawMe(){let g=my.can.g my.can.clear() if(my.startQ){g.fillStyle='hsla(240,100%,70%,1)' g.font='bold 16px Arial' g.textAlign='center' g.fillText('Draw a line segment '+my.typeDescr+' to this line',my.wd/2,20) my.startQ=false} drawBG(g.canvas.width,g.canvas.height) g.lineWidth=2 my.exerLn.setLen(1000,true) g.strokeStyle='hsla(240,100%,70%,1)' my.exerLn.drawMe(g) if(goodQ()){g.strokeStyle='gold'}else{g.strokeStyle='rgba(0,0,256,1)'} my.userLn.drawMe(g)} function Pt(ix,iy){this.x=ix this.y=iy angleIn=0 angleOut=0} Pt.prototype.setxy=function(ix,iy){this.x=ix this.y=iy} Pt.prototype.getAngle=function(){return this.angleOut-this.angleIn} Pt.prototype.drawMe=function(g){g.fillStyle='rgba(0, 0, 255, 0.3)' g.beginPath() g.arc(this.x,this.y,20,0,2*Math.PI,false) g.closePath() g.fill()} Pt.prototype.getAvg=function(pts){let xSum=0 let ySum=0 for(let i=0;iMath.PI)degDiff-=Math.PI if(isNear(degDiff,Math.PI/2,toler)){return true} return false}} Line.prototype.getMidPt=function(){return new Pt((this.a.x+this.b.x)/2,(this.a.y+this.b.y)/2)} Line.prototype.getClosestPoint=function(toPt,inSegmentQ){let AP=toPt.translate(this.a,false) let AB=this.b.translate(this.a,false) let ab2=AB.x*AB.x+AB.y*AB.y let ap_ab=AP.x*AB.x+AP.y*AB.y let t=ap_ab/ab2 if(inSegmentQ){t=constrain(0,t,1)} return this.a.translate(AB.multiply(t))} Line.prototype.setLen=function(newLen,fromMidQ){let len=this.getLength() if(fromMidQ){let midPt=this.getMidPt() let halfPt=new Pt(this.a.x-midPt.x,this.a.y-midPt.y) halfPt.multiplyMe(newLen/len) this.a=midPt.translate(halfPt) this.b=midPt.translate(halfPt,false)}else{let diffPt=new Pt(this.a.x-this.b.x,this.a.y-this.b.y) diffPt.multiplyMe(newLen/len) this.b=this.a.translate(diffPt,false)}} Line.prototype.getAngle=function(){return Math.atan2(this.b.y-this.a.y,this.b.x-this.a.x)} Line.prototype.setAngle=function(angle){let len=dist(this.b.x-this.a.x,this.b.y-this.a.y) if(len==0){len=100 this.a.x=this.a.x-(len/2)*Math.cos(angle) this.a.y=this.a.y-(len/2)*Math.sin(angle) this.b.x=this.a.x+len*Math.cos(angle) this.b.y=this.a.y+len*Math.sin(angle)}else{this.b.x=this.a.x+len*Math.cos(angle) this.b.y=this.a.y+len*Math.sin(angle)}} function dist(dx,dy){return Math.sqrt(dx*dx+dy*dy)} function isNear(checkVal,centralVal,limitVal){if(checkValcentralVal+limitVal)return false return true} function getJSQueryVar(varName,defaultVal){let scripts=document.getElementsByTagName('script') let lastScript=scripts[scripts.length-1] let scriptName=lastScript.src let bits=scriptName.split('?') if(bits.length<2)return defaultVal let query=bits[1] console.log('query: ',query) let vars=query.split('&') for(let i=0;i{if(cls.length==0)cls='btn' return '