new file: Files/flashplayer_32_sa.exe new file: favicon.ico new file: globe.gif new file: imgs/download.png new file: imgs/zuck.jpg new file: index.html new file: other.ico new file: script.js new file: site.webmanifest new file: sitemap.html new file: styles/backround.css new file: styles/border.css new file: styles/fonts/Titillium_Web/OFL.txt new file: styles/fonts/Titillium_Web/TitilliumWeb-Black.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Bold.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-BoldItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-ExtraLight.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-ExtraLightItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Italic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Light.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-LightItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Regular.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-SemiBold.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-SemiBoldItalic.ttf new file: styles/fonts/webfontkit-20221027-163353/generator_config.txt new file: styles/fonts/webfontkit-20221027-163353/specimen_files/grid_12-825-55-15.css new file: styles/fonts/webfontkit-20221027-163353/specimen_files/specimen_stylesheet.css new file: styles/fonts/webfontkit-20221027-163353/stylesheet.css new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-demo.html new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-webfont.woff new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-webfont.woff2 new file: styles/fonts/webfontkit-20221027-165950/generator_config.txt new file: styles/fonts/webfontkit-20221027-165950/specimen_files/grid_12-825-55-15.css new file: styles/fonts/webfontkit-20221027-165950/specimen_files/specimen_stylesheet.css new file: styles/fonts/webfontkit-20221027-165950/stylesheet.css new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-demo.html new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-webfont.woff new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-webfont.woff2 new file: styles/style.css new file: tools/2048/.gitignore new file: tools/2048/.jshintrc new file: tools/2048/CONTRIBUTING.md new file: tools/2048/LICENSE.txt new file: tools/2048/README.md new file: tools/2048/Rakefile new file: tools/2048/favicon.ico new file: tools/2048/index.html new file: tools/2048/js/animframe_polyfill.js new file: tools/2048/js/application.js new file: tools/2048/js/bind_polyfill.js new file: tools/2048/js/classlist_polyfill.js new file: tools/2048/js/game_manager.js new file: tools/2048/js/grid.js new file: tools/2048/js/html_actuator.js new file: tools/2048/js/keyboard_input_manager.js new file: tools/2048/js/local_storage_manager.js new file: tools/2048/js/tile.js new file: tools/2048/meta/apple-touch-icon.png new file: tools/webretro/cores/neocd_libretro.js new file: tools/webretro/cores/neocd_libretro.wasm new file: tools/webretro/cores/nestopia_libretro.js new file: tools/webretro/cores/nestopia_libretro.wasm new file: tools/webretro/cores/o2em_libretro.js new file: tools/webretro/cores/o2em_libretro.wasm new file: tools/webretro/cores/opera_libretro.js new file: tools/webretro/cores/opera_libretro.wasm
406 lines
19 KiB
JavaScript
406 lines
19 KiB
JavaScript
let my={}
|
|
function init(){let version='0.84'
|
|
let s=''
|
|
s+='<div style="margin:auto; display:block;">'
|
|
s+='<div id="hdr" style="position:absolute; display:block; width:100px; height: 40px; z-index:100;">'
|
|
s+=wrap({tag:'btn',style:'width:90px; z-index:44;',fn:'optPop()'},'Restart')
|
|
s+=wrap({tag:'btn',style:'width:90px; z-index:44;',fn:'moreBtn()'},'Jigsaws')
|
|
s+=wrap({id:'imageBtn',tag:'btn',class:'hi',style:'width:90px; z-index:44;',fn:'toggleImg()'},'Image')
|
|
s+=getPopHTML()
|
|
s+='</div>'
|
|
s+='<div style="height: 40px;"></div>'
|
|
s+='<canvas id="canvasId" style="display:block; margin:auto; z-index:1; text-align: center;"></canvas>'
|
|
s+='<div id="jig" style="position:absolute; left:0; top:0; width:100px; height: 100px;"></div>'
|
|
s+=wrap({cls:'copyrt',pos:'abs',style:'left:5px; bottom:3px'},`© 2021 MathsIsFun.com v${version}`)
|
|
s+='</div>'
|
|
docInsert(s)
|
|
my.can=new Can('canvasId',1000,1000,1)
|
|
my.jig=document.getElementById('jig')
|
|
my.fileName='passiflora.html'
|
|
let imgName=getQueryVariable('img')
|
|
if(imgName){imgName=decodeURIComponent(imgName)
|
|
imgName=imgName.replace(/[^0-9A-Za-z\-\.]+/g,'')
|
|
my.fileName=imgName}
|
|
console.log('fileName',my.fileName)
|
|
my.imgHome=(document.domain=='localhost'?'/mathsisfun':'')+'/puzzles/images/jigsaw/'
|
|
my.rowN=4
|
|
my.colN=4
|
|
my.pWd=100
|
|
my.pHt=100
|
|
my.animN=0
|
|
my.animTp=0
|
|
my.imgQ=true
|
|
my.p=[]
|
|
window.addEventListener('mousedown',mouseDown,false)
|
|
my.touchSelPiece=null
|
|
my.touchPt=null
|
|
my.jig.addEventListener('touchstart',ontouchstart,false)
|
|
my.jig.addEventListener('touchmove',ontouchmove,false)
|
|
my.jig.addEventListener('touchend',ontouchend,false)
|
|
optPop()}
|
|
function toggleImg(){my.imgQ=!my.imgQ
|
|
if(my.imgQ){loadImg(0.5,false)}else{loadImg(0,false)}
|
|
toggleBtn('imageBtn',my.imgQ)}
|
|
function toggleBtn(btn,onq){if(onq){document.getElementById(btn).classList.add('hi')
|
|
document.getElementById(btn).classList.remove('lo')}else{document.getElementById(btn).classList.add('lo')
|
|
document.getElementById(btn).classList.remove('hi')}}
|
|
function ontouchstart(evt){evt.preventDefault()
|
|
let touch=evt.targetTouches[0]
|
|
startIt(touch.clientX,touch.clientY)}
|
|
function ontouchmove(evt){let touch=evt.targetTouches[0]
|
|
my.touchSelPiece.moveTo(touch.pageX-my.touchPt.x,touch.pageY-my.touchPt.y)
|
|
my.touchPt=new Point(touch.pageX,touch.pageY)
|
|
evt.preventDefault()}
|
|
function ontouchend(evt){finishIt()
|
|
evt.preventDefault()}
|
|
function moreBtn(){window.location.href='http://www.mathsisfun.com/puzzles/jigsaw-puzzles-index.html'}
|
|
function optPop(){let pop=document.getElementById('optpop')
|
|
pop.style.transitionDuration='0.3s'
|
|
pop.style.opacity=1
|
|
pop.style.zIndex=12
|
|
pop.style.left='120px'
|
|
pop.style.top='20px'}
|
|
function userUpdate(){}
|
|
function getPopHTML(){let s=''
|
|
s+='<div id="optpop" style="position:absolute; left:-450px; top:40px; width:300px; padding: 5px; border: 1px solid red; border-radius: 9px; background-color: #88aaff; box-shadow: 10px 10px 5px 0px rgba(40,40,40,0.75); transition: all linear 0.3s; opacity:0; ">'
|
|
let opts=[]
|
|
for(let i=3;i<=12;i++){opts.push({name:i,descr:i})}
|
|
s+=wrap({id:'rowN',tag:'sel',lbl:'Rows:',txt:'6',opts:opts})
|
|
s+=' '
|
|
s+=wrap({id:'colN',tag:'sel',lbl:'Cols:',txt:'6',opts:opts})
|
|
s+='<div style="float:right; margin: 0 0 5px 10px;">'
|
|
s+='<button onclick="editYes()" style="z-index:2; font: 22px Arial;" class="btn" >✔</button>'
|
|
s+='</div>'
|
|
s+='</div>'
|
|
return s}
|
|
function editYes(){let pop=document.getElementById('optpop')
|
|
pop.style.opacity=0
|
|
pop.style.zIndex=1
|
|
pop.style.left='-500px'
|
|
my.rowN=document.getElementById('rowN').value
|
|
my.rowN=Math.max(3,Math.min(my.rowN>>0,12))
|
|
my.colN=document.getElementById('colN').value
|
|
my.colN=Math.max(3,Math.min(my.colN>>0,12))
|
|
if(my.imgQ){loadImg(0.5,true)}else{loadImg(0,true)}}
|
|
function doAnim(){let pc=my.p[my.animN]
|
|
if(my.animTp%2==0){pc.left=pc.canvas.style.left
|
|
let left=parseFloat(pc.canvas.style.left)
|
|
pc.canvas.style.left=left-(Math.random()-0.5)*60+'px'
|
|
pc.top=pc.canvas.style.top
|
|
let top=parseFloat(pc.canvas.style.top)
|
|
pc.canvas.style.top=top-(Math.random()-0.5)*60+'px'}else{pc.canvas.style.left=pc.left
|
|
pc.canvas.style.top=pc.top}
|
|
my.animN++
|
|
if(my.animN<my.rowN*my.colN){requestAnimationFrame(doAnim)}else{my.animN=0
|
|
my.animTp++
|
|
if(my.animTp<6)requestAnimationFrame(doAnim)}}
|
|
function jiggle(){my.animN=0
|
|
my.animTp=0
|
|
doAnim()}
|
|
function loadImg(alpha,newQ){let g=my.can.g
|
|
let el=my.can.el
|
|
if(newQ){my.can.clear()
|
|
my.jig.innerHTML=''}
|
|
let image=new Image()
|
|
image.onload=function(){console.log('image.onload',this,this.width,this.height)
|
|
let ratio=my.can.ratio
|
|
el.width=this.width*ratio
|
|
el.style.width=this.width+'px'
|
|
el.height=this.height*ratio
|
|
el.style.height=this.height+'px'
|
|
g.save()
|
|
g.globalAlpha=alpha
|
|
g.drawImage(this,0,0)
|
|
g.restore()
|
|
g.fillStyle='rgba(255,255,255,'+alpha+')'
|
|
g.fillRect(0,0,this.width,this.height)
|
|
if(newQ)go(this)}
|
|
image.src=my.imgHome+my.fileName}
|
|
function getRandPts(){let rect=my.jig.getBoundingClientRect()
|
|
let pts=[]
|
|
let xCurr=-rect.left
|
|
let yCurr=0
|
|
for(let i=0;i<my.colN*my.rowN;i++){pts.push({x:xCurr+Math.random()*my.pWd,y:yCurr+Math.random()*my.pHt,})
|
|
xCurr+=my.pWd*1.5
|
|
if(xCurr>=document.body.clientWidth-rect.left-my.pWd*2){xCurr=-rect.left
|
|
yCurr+=my.pHt*1.5}}
|
|
return shuffle(pts)}
|
|
function shuffle(array){let tmp,current,top=array.length
|
|
if(top)
|
|
while(--top){current=Math.floor(Math.random()*(top+1))
|
|
tmp=array[current]
|
|
array[current]=array[top]
|
|
array[top]=tmp}
|
|
return array}
|
|
function go(img){my.pWd=img.width/my.colN
|
|
my.pHt=img.height/my.rowN
|
|
console.log('go',img,my.pWd,my.pHt)
|
|
let pts=getRandPts()
|
|
let ptNo=0
|
|
let p=[]
|
|
let count=0
|
|
for(let l=0;l<my.rowN;l++){for(let k=0;k<my.colN;k++){p.push(new PuzzlePiece({rotation:0,imgwidth:img.width,imgheight:img.height,width:my.pWd,height:my.pHt,image:img,imagepoint:new Point(k*my.pWd,l*my.pHt),top:{first:new Point(k*my.pWd,l*my.pHt),last:new Point(k*my.pWd+my.pWd,l*my.pHt),},right:{first:new Point(k*my.pWd+my.pWd,l*my.pHt),last:new Point(k*my.pWd+my.pWd,l*my.pHt+my.pHt),},bot:{first:new Point(k*my.pWd+my.pWd,l*my.pHt+my.pHt),last:new Point(k*my.pWd,l*my.pHt+my.pHt),},left:{first:new Point(k*my.pWd,l*my.pHt+my.pHt),last:new Point(k*my.pWd,l*my.pHt),},}))
|
|
p[p.length-1].canvas.style.setProperty('left',pts[ptNo].x+'px')
|
|
p[p.length-1].canvas.style.setProperty('top',pts[ptNo].y+'px')
|
|
ptNo++
|
|
if(k!==0){let temp=p[p.length-2].right.points
|
|
p[p.length-2].pieceright=p[p.length-1]
|
|
p[p.length-1].pieceleft=p[p.length-2]
|
|
p[p.length-1].left.points=[]
|
|
for(let i=0;i<temp.length;i++){p[p.length-1].left.points.push(new Point(temp[i].x-p[p.length-1].width,temp[i].y))}
|
|
p[p.length-1].left.points.reverse()}
|
|
if(l!==0){let temp2=p[count-my.colN].bot.points
|
|
p[count-my.colN].piecebot=p[p.length-1]
|
|
p[p.length-1].piecetop=p[count-my.colN]
|
|
p[count].top.points=[]
|
|
for(let i=0;i<temp2.length;i++){p[count].top.points.push(new Point(temp2[i].x,temp2[i].y-p[count].height))}
|
|
p[count].top.points.reverse()}
|
|
count++}}
|
|
for(let i=0;i<p.length;i++){p[i].canvas.style.zIndex=i
|
|
p[i].display()
|
|
p[i].connected.push(p[i])
|
|
if(false){for(let rotation=Math.floor(Math.random()*4.0);rotation<=4;rotation++){p[i].rotate(p[i])}}}
|
|
my.p=p}
|
|
function clone(obj){if(null===obj||'object'!=typeof obj)return obj
|
|
let copy=obj.constructor()
|
|
for(let attr in obj){if(obj.hasOwnProperty(attr))copy[attr]=obj[attr]}
|
|
return copy}
|
|
function Point(x,y){this.x=x
|
|
this.y=y
|
|
this.d=Math.sqrt(x*x+y*y)
|
|
return this}
|
|
Point.prototype={}
|
|
let PuzzlePiece=(function(){function PuzzlePiece(obj){this.imgtop=clone(obj.top)
|
|
this.rotation=obj.rotation
|
|
this.image=obj.image
|
|
this.width=obj.width+0
|
|
this.height=obj.height+0
|
|
this.canvas=document.createElement('canvas')
|
|
this.canvas.rotation=0
|
|
this.connected=[]
|
|
this.canvas.setAttribute('style','position:absolute;')
|
|
this.canvas.setAttribute('width',obj.width*3)
|
|
this.canvas.setAttribute('height',obj.height*3)
|
|
this.canvas.style.setProperty('top',this.imgtop.first.y+1+'px')
|
|
this.canvas.style.setProperty('left',this.imgtop.first.x+1+'px')
|
|
this.context=this.canvas.getContext('2d')
|
|
my.jig.appendChild(this.canvas)
|
|
let lt=obj.width
|
|
let tp=obj.height
|
|
this.top={first:new Point(lt-obj.width/2.0,tp-obj.height/2.0),last:new Point(lt+obj.width/2.0,tp-obj.height/2.0),}
|
|
this.right={first:new Point(lt+obj.width/2.0,tp-obj.height/2.0),last:new Point(lt+obj.width/2.0,tp+obj.height/2.0),}
|
|
this.bot={first:new Point(lt+obj.width/2.0,tp+obj.height/2.0),last:new Point(lt-obj.width/2.0,tp+obj.height/2.0),}
|
|
this.left={first:new Point(lt-obj.width/2.0,tp+obj.height/2.0),last:new Point(lt-obj.width/2.0,tp-obj.height/2.0),}
|
|
if(obj.left.first.x>0){this.left.points=this.makeSide(this.left)}else{this.left.points=[]
|
|
this.left.points.push(this.left.first)
|
|
this.left.points.push(this.left.last)}
|
|
if(obj.top.first.y>0){this.top.points=this.makeSide(this.top)}else{this.top.points=[]
|
|
this.top.points.push(this.top.first)
|
|
this.top.points.push(this.top.last)}
|
|
if(parseFloat(obj.right.first.x)>=parseFloat(obj.imgwidth)-1){this.right.points=[]
|
|
this.right.points.push(this.right.first)
|
|
this.right.points.push(this.right.last)}else{this.right.points=this.makeSide(this.right)}
|
|
if(parseFloat(obj.bot.last.y)>=parseFloat(obj.imgheight)-1){this.bot.points=[]
|
|
this.bot.points.push(this.bot.first)
|
|
this.bot.points.push(this.bot.last)}else{this.bot.points=this.makeSide(this.bot)}
|
|
this.display=function(){this.context.beginPath()
|
|
this.dBezierCurve(this.top.points)
|
|
this.dBezierCurve(this.right.points)
|
|
this.dBezierCurve(this.bot.points)
|
|
this.dBezierCurve(this.left.points)
|
|
this.context.closePath()
|
|
this.context.save()
|
|
this.context.clip()
|
|
this.context.drawImage(this.image,my.pWd/2-this.imgtop.first.x,my.pHt/2-this.imgtop.first.y)
|
|
this.context.strokeStyle='#333'
|
|
this.context.lineWidth=1
|
|
this.context.stroke()}}
|
|
return PuzzlePiece})()
|
|
PuzzlePiece.prototype={rotate:function(around){this.connected.forEach(function(element){let temptop=parseFloat(around.canvas.style.top)-(parseFloat(around.canvas.style.left)-parseFloat(element.canvas.style.left))
|
|
let templeft=parseFloat(around.canvas.style.left)+(parseFloat(around.canvas.style.top)-parseFloat(element.canvas.style.top))
|
|
element.canvas.style.setProperty('top',temptop+'px')
|
|
element.canvas.style.setProperty('left',templeft+'px')
|
|
element.canvas.getContext('2d').restore()
|
|
element.canvas.getContext('2d').clearRect(0,0,element.canvas.width,element.canvas.height)
|
|
element.context.translate(element.canvas.width/2.0,element.canvas.height/2.0)
|
|
element.canvas.getContext('2d').rotate(Math.PI/2.0)
|
|
element.rotation+=1
|
|
element.rotation%=4
|
|
element.context.translate(-(element.canvas.width/2.0),-(element.canvas.height/2.0))
|
|
element.display()
|
|
let origtop=element.piecetop
|
|
let origright=element.pieceright
|
|
let origbot=element.piecebot
|
|
let origleft=element.pieceleft
|
|
element.piecetop=null
|
|
element.pieceright=null
|
|
element.piecebot=null
|
|
element.pieceleft=null
|
|
element.piecetop=origleft
|
|
element.pieceright=origtop
|
|
element.piecebot=origright
|
|
element.pieceleft=origbot})},moveTo:function(x,y){this.connected.forEach(function(element){element.canvas.style.setProperty('left',parseFloat(element.canvas.style.left)+x+'px')
|
|
element.canvas.style.setProperty('top',parseFloat(element.canvas.style.top)+y+'px')})},dBezierCurve:function(){let controlpoint=3.5
|
|
let args=Array.prototype.slice.call(arguments)
|
|
if(args[0].length>1){args=args[0]}
|
|
if(args.length<=2){this.context.lineTo(args[0].x,args[0].y)
|
|
this.context.lineTo(args[1].x,args[1].y)
|
|
return}
|
|
let a=[]
|
|
a.push(args[0])
|
|
for(let j=0;j<args.length;j++){a.push(args[j])}
|
|
a.push(args[args.length-1])
|
|
args=a
|
|
for(let i=2;i<args.length-1;i++){let before=new Point(args[(i+(args.length-1))%args.length].x,args[(i+(args.length-1))%args.length].y)
|
|
let after=new Point(args[(i+(args.length+1))%args.length].x,args[(i+(args.length+1))%args.length].y)
|
|
let current=new Point(args[(i+args.length)%args.length].x,args[(i+args.length)%args.length].y)
|
|
let before2=new Point(args[(i+(args.length-2))%args.length].x,args[(i+(args.length-2))%args.length].y)
|
|
let mid1=new Point(before.x-(before2.x-current.x)/controlpoint,before.y-(before2.y-current.y)/controlpoint)
|
|
let mid2=new Point(current.x+(before.x-after.x)/controlpoint,current.y+(before.y-after.y)/controlpoint)
|
|
this.context.bezierCurveTo(mid1.x,mid1.y,mid2.x,mid2.y,current.x,current.y)}},makeSide:function(eobj){let lp=[]
|
|
let d=new Point(eobj.first.x-eobj.last.x,eobj.first.y-eobj.last.y),midpoint=new Point((eobj.first.x+eobj.last.x)/2.0,(eobj.first.y+eobj.last.y)/2.0),r=Math.round(Math.random())*2.0-1,rd=new Point((d.x/6.0)*(Math.random()*0.5+0.7),(d.y/6.0)*(Math.random()*0.5+0.7)),pt1=new Point(midpoint.x+rd.x+(rd.y/2.0)*Math.random(),midpoint.y+rd.y+(rd.x/2.0)*Math.random()),pt2=new Point(midpoint.x-rd.x+(rd.y/2.0)*Math.random(),midpoint.y-rd.y+(rd.x/2.0)*Math.random())
|
|
lp.push(new Point(eobj.first.x,eobj.first.y))
|
|
lp.push(pt1)
|
|
lp.push(new Point(pt1.x+rd.y*r,pt1.y+rd.x*r))
|
|
lp.push(new Point(pt2.x+rd.y*r,pt2.y+rd.x*r))
|
|
lp.push(pt2)
|
|
lp.push(new Point(eobj.last.x,eobj.last.y))
|
|
return lp.splice(0)},}
|
|
function mouseDown(event){startIt(event.pageX,event.pageY)}
|
|
function startIt(x,y){let p=my.p
|
|
for(let j=0;j<p.length;j++){p[j].canvas.style.zIndex=p.length-j}
|
|
for(let i=0;i<p.length;i++){let that=p[i].canvas
|
|
let rect=my.jig.getBoundingClientRect()
|
|
if(that.getContext('2d').isPointInPath(x-parseInt(that.style.getPropertyValue('left'),10),y-parseInt(that.style.getPropertyValue('top'),10))){document.selectedpiece=p[i]
|
|
my.touchSelPiece=document.selectedpiece
|
|
my.touchPt=new Point(x,y)
|
|
that=p.splice(i,1)[0]
|
|
p.unshift(that)
|
|
that=that.canvas
|
|
that.style.zIndex=p.length+1
|
|
that.mouse=new Point(x,y)
|
|
document.selected=that
|
|
document.onmousemove=mousemove
|
|
document.onmouseup=mouseup
|
|
return}}}
|
|
function dblclick(event){for(let i=0;i<my.p.length;i++){let that=my.p[i]
|
|
if(that.canvas.getContext('2d').isPointInPath(event.pageX-parseInt(that.canvas.style.getPropertyValue('left'),10),event.pageY-parseInt(that.canvas.style.getPropertyValue('top'),10))){that.rotate(that)
|
|
return}}}
|
|
function mousemove(evt){document.selectedpiece.moveTo(evt.pageX-document.selected.mouse.x,evt.pageY-document.selected.mouse.y)
|
|
document.selected.mouse=new Point(evt.pageX,evt.pageY)}
|
|
function mouseup(evt){finishIt(evt.pageX,evt.pageY)}
|
|
function finishIt(x,y){document.selectedpiece.moveTo(x-document.selected.mouse.x,y-document.selected.mouse.y)
|
|
document.selectedpiece.connected.forEach(function(element){checkForMatches(element)})
|
|
document.selectedpiece=null
|
|
document.onmouseup=''
|
|
document.onmousemove=''
|
|
document.selected.mouse=''
|
|
document.selected=null
|
|
checkDone()}
|
|
function contains(a,obj){for(let i=0;i<a.length;i++){if(a[i]===obj){return true}}
|
|
return false}
|
|
Array.prototype.myUnique=function(){let r=[]
|
|
o:for(let i=0;i<this.length;i++){for(let x=0;x<r.length;x++){if(r[x]===this[i]){continue o}}
|
|
r[r.length]=this[i]}
|
|
return r}
|
|
function checkForMatches(e){let top=parseFloat(e.canvas.style.top)
|
|
let left=parseFloat(e.canvas.style.left)
|
|
let accuracy=5.0
|
|
let topmatchmin=top-e.height/accuracy
|
|
let topmatchmax=top+e.height/accuracy
|
|
let leftmatchmin=left-e.width/accuracy
|
|
let leftmatchmax=left+e.width/accuracy
|
|
if(typeof e.piecetop!=='undefined'){let toptop=parseFloat(e.piecetop.canvas.style.top)
|
|
let topleft=parseFloat(e.piecetop.canvas.style.left)
|
|
if(toptop+e.height>topmatchmin&&toptop+e.height<topmatchmax&&topleft>leftmatchmin&&topleft<leftmatchmax&&e.rotation==e.piecetop.rotation){e.piecetop.moveTo(left-topleft,top-(toptop+e.height))
|
|
let c=e.connected.concat(e.piecetop.connected).myUnique()
|
|
c.forEach(function(element,index,array){element.connected=array})}}
|
|
if(typeof e.pieceright!=='undefined'){let righttop=parseFloat(e.pieceright.canvas.style.top)
|
|
let rightleft=parseFloat(e.pieceright.canvas.style.left)
|
|
if(righttop>topmatchmin&&righttop<topmatchmax&&rightleft-e.width>leftmatchmin&&rightleft-e.width<leftmatchmax&&e.rotation==e.pieceright.rotation){e.pieceright.moveTo(left-(rightleft-e.width),top-righttop)
|
|
let d=e.connected.concat(e.pieceright.connected).myUnique()
|
|
d.forEach(function(element,index,array){element.connected=array})}}
|
|
if(typeof e.pieceleft!=='undefined'){let lefttop=parseFloat(e.pieceleft.canvas.style.top)
|
|
let leftleft=parseFloat(e.pieceleft.canvas.style.left)
|
|
if(lefttop>topmatchmin&&lefttop<topmatchmax&&leftleft+e.width>leftmatchmin&&leftleft+e.width<leftmatchmax&&e.rotation==e.pieceleft.rotation){e.pieceleft.moveTo(left-(leftleft+e.width),top-lefttop)
|
|
let f=e.connected.concat(e.pieceleft.connected).myUnique()
|
|
f.forEach(function(element,index,array){element.connected=array})}}
|
|
if(typeof e.piecebot!=='undefined'){let bottop=parseFloat(e.piecebot.canvas.style.top)
|
|
let botleft=parseFloat(e.piecebot.canvas.style.left)
|
|
if(bottop-e.height>topmatchmin&&bottop-e.height<topmatchmax&&botleft>leftmatchmin&&botleft<leftmatchmax&&e.rotation==e.piecebot.rotation){e.piecebot.moveTo(left-botleft,top-(bottop-e.height))
|
|
let g=e.connected.concat(e.piecebot.connected).myUnique()
|
|
g.forEach(function(element,index,array){element.connected=array})}}}
|
|
function checkDone(conn){conn=my.p[0].connected
|
|
if(conn.length==my.colN*my.rowN){jiggle()}}
|
|
function getQueryVariable(variable){let query=window.location.search.substring(1)
|
|
let vars=query.split('&')
|
|
for(let i=0;i<vars.length;i++){let pair=vars[i].split('=')
|
|
if(pair[0]==variable){return pair[1]}}
|
|
return false}
|
|
function docInsert(s){let div=document.createElement('div')
|
|
div.innerHTML=s
|
|
let script=document.currentScript
|
|
script.parentElement.insertBefore(div,script)}
|
|
class Can{constructor(id,wd,ht,ratio){this.id=id
|
|
this.wd=wd
|
|
this.ht=ht
|
|
this.ratio=ratio
|
|
let el=document.getElementById(id)
|
|
el.width=wd*ratio
|
|
el.style.width=wd+'px'
|
|
el.height=ht*ratio
|
|
el.style.height=ht+'px'
|
|
this.g=el.getContext('2d')
|
|
this.g.setTransform(ratio,0,0,ratio,0,0)
|
|
this.el=el
|
|
return this}
|
|
clear(){this.g.clearRect(0,0,this.wd,this.ht)}
|
|
mousePos(ev){let bRect=this.el.getBoundingClientRect()
|
|
let mouseX=(ev.clientX-bRect.left)*(this.el.width/this.ratio/bRect.width)
|
|
let mouseY=(ev.clientY-bRect.top)*(this.el.height/this.ratio/bRect.height)
|
|
return[mouseX,mouseY]}}
|
|
function wrap({id='',cls='',pos='rel',style='',txt='',tag='div',lbl='',fn='',opts=[]},...mores){let s=''
|
|
s+='\n'
|
|
txt+=mores.join('')
|
|
s+={btn:()=>{if(cls.length==0)cls='btn'
|
|
return '<button onclick="'+fn+'"'},can:()=>'<canvas',div:()=>'<div',edit:()=>'<textarea onkeyup="'+fn+'" onchange="'+fn+'"',inp:()=>{if(cls.length==0)cls='input'
|
|
let s=''
|
|
s+=lbl.length>0?'<label class="label">'+lbl+' ':''
|
|
s+='<input value="'+txt+'"'
|
|
s+=fn.length>0?' oninput="'+fn+'" onchange="'+fn+'"':''
|
|
return s},out:()=>{pos='dib'
|
|
if(cls.length==0)cls='output'
|
|
let s=''
|
|
s+=lbl.length>0?'<label class="label">'+lbl+' ':''
|
|
s+='<span '
|
|
return s},rad:()=>{if(cls.length==0)cls='radio'
|
|
return '<form'+(fn.length>0?(s+=' onclick="'+fn+'"'):'')},sel:()=>{if(cls.length==0)cls='select'
|
|
let s=''
|
|
s+=lbl.length>0?'<label class="label">'+lbl+' ':''
|
|
s+='<select '
|
|
s+=fn.length>0?' onchange="'+fn+'"':''
|
|
return s},sld:()=>'<input type="range" '+txt+' oninput="'+fn+'" onchange="'+fn+'"',}[tag]()||''
|
|
if(id.length>0)s+=' id="'+id+'"'
|
|
if(cls.length>0)s+=' class="'+cls+'"'
|
|
if(pos=='dib')s+=' style="position:relative; display:inline-block;'+style+'"'
|
|
if(pos=='rel')s+=' style="position:relative; '+style+'"'
|
|
if(pos=='abs')s+=' style="position:absolute; '+style+'"'
|
|
s+={btn:()=>'>'+txt+'</button>',can:()=>'></canvas>',div:()=>' >'+txt+'</div>',edit:()=>' >'+txt+'</textarea>',inp:()=>'>'+(lbl.length>0?'</label>':''),out:()=>' >'+txt+'</span>'+(lbl.length>0?'</label>':''),rad:()=>{let s=''
|
|
s+='>\n'
|
|
for(let i=0;i<opts.length;i++){let chk=''
|
|
if(i==0)chk='checked'
|
|
s+='<input type="radio" id="r'+i+'" name="typ" style="cursor:pointer;" value="'+opts[i][0]+'" '+chk+' />\n'
|
|
s+='<label for="r'+i+'" style="cursor:pointer;">'+opts[i][1]+'</label><br/>\n'}
|
|
s+='</form>'
|
|
return s},sel:()=>{let s=''
|
|
s+='>\n'
|
|
for(let i=0;i<opts.length;i++){let opt=opts[i]
|
|
let idStr=id+i
|
|
let chkStr=opt.descr==txt?' selected ':''
|
|
s+='<option id="'+idStr+'" value="'+opt.name+'"'+chkStr+'>'+opt.descr+'</option>\n'}
|
|
s+='</select>'
|
|
if(lbl.length>0)s+='</label>'
|
|
return s},sld:()=>'>',}[tag]()||''
|
|
s+='\n'
|
|
return s.trim()}
|
|
init() |