From 8d0c8aae016f3b669d6d80c5bfb22342de5cd357 Mon Sep 17 00:00:00 2001 From: era Date: Fri, 4 Oct 2024 15:22:18 -0700 Subject: [PATCH] cdn distribution should work --- README.md | 2 +- dist/docs/index.html | 2 +- dist/min.js | 2 +- index.ts | 18 +- package.json | 4 +- public/docs/index.html | 852 +++++++++++++++++++++++++++++++---------- 6 files changed, 666 insertions(+), 214 deletions(-) diff --git a/README.md b/README.md index 5bb52cb..018dd56 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ via npm via unpkg cdn -`` via jsdeliver cdn diff --git a/dist/docs/index.html b/dist/docs/index.html index 62044ee..6934315 100644 --- a/dist/docs/index.html +++ b/dist/docs/index.html @@ -3,7 +3,7 @@ - + docs diff --git a/dist/min.js b/dist/min.js index cd33c34..165ab85 100644 --- a/dist/min.js +++ b/dist/min.js @@ -1 +1 @@ -(function(){const y=document.createElement("link").relList;if(y&&y.supports&&y.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))a(i);new MutationObserver(i=>{for(const t of i)if(t.type==="childList")for(const e of t.addedNodes)e.tagName==="LINK"&&e.rel==="modulepreload"&&a(e)}).observe(document,{childList:!0,subtree:!0});function n(i){const t={};return i.integrity&&(t.integrity=i.integrity),i.referrerPolicy&&(t.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?t.credentials="include":i.crossOrigin==="anonymous"?t.credentials="omit":t.credentials="same-origin",t}function a(i){if(i.ep)return;i.ep=!0;const t=n(i);fetch(i.href,t)}})();const k=(w,y)=>(w%y+y)%y,S=()=>"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,w=>{const y=Math.floor(Math.random()*16);return(w=="x"?y:y&3|8).toString(16)});class V{constructor(y){if(this.postConstructor=()=>{this.postConstructorCalls++,this.paused||requestAnimationFrame(this.animate)},this.setConfig=n=>{this.backgroundColour=n.backgroundColour??this.backgroundColour,this.currProgress=n.currProgress??this.currProgress,this.lastProgress=n.lastProgress??this.lastProgress,this.rest=n.rest??this.rest,this.fps=n.fps??this.fps,this.cycleDuration_ms=n.cycleDuration_ms??this.cycleDuration_ms,this.currIteration=n.currIteration??this.currIteration,this.nIterations=n.nIterations??this.nIterations,this.paused=n.paused??this.paused,this.colours=n.colours??this.colours,this.opacity=n.opacity??this.opacity,this.opacityDelta=n.opacityDelta??this.opacityDelta,this.timingFunction=n.timingFunction??this.timingFunction,this.customTimingFunction=n.customTimingFunction??this.customTimingFunction,this.drawStyle=n.drawStyle??this.drawStyle,this.canvas.width=n.canvasWidth??this.canvas.width,this.canvas.height=n.canvasHeight??this.canvas.height,this.origin={x:Math.floor(this.canvas.width/2),y:Math.floor(this.canvas.height/2)}},this.draw=()=>{this.context.clearRect(0,0,this.canvas.width,this.canvas.height);const a=1e3/this.fps/this.cycleDuration_ms;this.frame=Math.floor(this.currProgress/a),this.lastDraw=performance.now(),this.backgroundColour!=null&&(this.context.fillStyle=this.backgroundColour,this.context.fillRect(0,0,this.canvas.width,this.canvas.height))},this.step=()=>{this.seek(1)},this.seek=n=>{const i=1e3/this.fps/this.cycleDuration_ms;this.lastProgress=this.currProgress,this.currProgress=(1+this.currProgress+n*i)%1,this.lastProgress===1&&(this.currProgress=0),this.draw()},this.animate=()=>{if(this.paused)return;requestAnimationFrame(this.animate);const n=performance.now(),a=n-this.lastDraw,i=1e3/this.fps;athis.currProgress&&(this.currIteration++,this.currIteration>=this.nIterations&&this.pause()),this.draw())},this.getProgress=n=>{switch(this.timingFunction){case"sinusoidal":return this.getProgressSinusoidal(n);case"quadratic":return this.getProgressExponential(2,n);case"cubic":return this.getProgressExponential(3,n);case"custom":if(this.customTimingFunction==null)throw new Error("Custom timing function does not exist.");return this.customTimingFunction(n);default:return this.getProgressLinear(n)}},this.getProgressLinear=n=>{const a=n?(this.currProgress+1+n)%1:this.currProgress;return Math.min(1,a/(1-this.rest))},this.getProgressExponential=(n,a)=>{const i=a?(this.currProgress+1+a)%1:this.currProgress,t=Math.min(1,i/(1-this.rest));return Math.pow(t,n)},this.getProgressSinusoidal=n=>{const a=n?(this.currProgress+1+n)%1:this.currProgress,i=Math.min(1,a/(1-this.rest));return .5+Math.sin((i-.5)*Math.PI)/2},this.play=()=>{if(!this.paused)return;this.paused=!1;const n=performance.now();this.lastDraw=n,this.pauseDuration+=n-this.pauseTimestamp,requestAnimationFrame(this.animate)},this.pause=()=>{this.paused||(this.paused=!0,this.pauseTimestamp=performance.now())},this.ctxDraw=()=>{this.drawStyle=="fill"?this.context.fill():this.context.stroke()},this.ctxMoveToVector=n=>{this.context.moveTo(n.x,n.y)},this.ctxLineToVector=n=>{this.context.lineTo(n.x,n.y)},this.ctxCircToVector=(n,a,i)=>{const t=this.circularBezierControlPoints(n,a,i);this.context.bezierCurveTo(t.cp1.x,t.cp1.y,t.cp2.x,t.cp2.y,a.x,a.y)},this.ctxSetColour=n=>{const a=k(n,this.colours.length),t=Math.floor(Math.max(0,this.opacity-(this.colours.length-1-a)*this.opacityDelta)*255).toString(16).padStart(2,"0"),e=`${this.colours[a]}${t}`;this.context.strokeStyle=e,this.context.fillStyle=e,this.currColour=e},this.ctxModifyOpacity=n=>{const a=this.currColour,i=a.slice(0,7),t=a.slice(7,9),e=parseInt(t,16),o=Math.floor(e+e*n).toString(16).padStart(2,"0"),r=`${i}${o}`;this.context.strokeStyle=r,this.context.fillStyle=r,this.currColour=r},this.drawDot=n=>{this.context.beginPath(),this.context.arc(this.origin.x+n.x,this.origin.y+n.y,2,0,2*Math.PI),this.context.fill()},this.circularBezierControlPoints=(n,a,i)=>{const t=i??{x:0,y:0},e=n.x-t.x,s=n.y-t.y,o=a.x-t.x,r=a.y-t.y,u=e*e+s*s,c=u+e*o+s*r,h=4/3*(Math.sqrt(2*u*c)-c)/(e*r-s*o),l=t.x+e-h*s,d=t.y+s+h*e,x=t.x+o+h*r,m=t.y+r-h*o;return{cp1:{x:l,y:d},cp2:{x,y:m}}},window.isSecureContext?this.id=crypto.randomUUID():this.id=S(),this.postConstructorCalls=0,this.start=performance.now(),this.lastDraw=this.start,this.lastMutationTimestamp=this.start,this.pauseTimestamp=0,this.pauseDuration=0,this.canvas=document.getElementById(y),this.canvas===null)throw new Error("Canvas element not found with id: "+y);this.canvas.setAttribute("data-animautomata-id",this.id),this.origin={x:Math.floor(this.canvas.width/2),y:Math.floor(this.canvas.height/2)},this.currColour="",this.context=this.canvas.getContext("2d"),this.frame=0,this.backgroundColour=null,this.currProgress=0,this.lastProgress=0,this.rest=0,this.fps=60,this.cycleDuration_ms=1500,this.currIteration=0,this.nIterations=1/0,this.paused=!1,this.colours=["#000000"],this.opacity=1,this.opacityDelta=0,this.timingFunction="sinusoidal",this.customTimingFunction=this.getProgressLinear,this.drawStyle="fill"}}class D extends V{constructor(y,n){super(y),this.parentDraw=this.draw,this.parentSetConfig=this.setConfig,this.setConfig=i=>{this.parentSetConfig(i),this.arcs=i.arcs??this.arcs,this.arcWidth=i.arcWidth??this.arcWidth,this.arcWidthDelta=i.arcWidthDelta??this.arcWidthDelta,this.arcAnchor=i.arcAnchor??this.arcAnchor,this.tailDelay=i.tailDelay??this.tailDelay,this.arcDelay=i.arcDelay??this.arcDelay,this.radius=i.radius??this.radius,this.radiusDelta=i.radiusDelta??this.radiusDelta,this.rotations=i.rotations??this.rotations,this.innerBorder=i.innerBorder??this.innerBorder,this.outerBorder=i.outerBorder??this.outerBorder,this.trackColour=i.trackColour??this.trackColour,this.lineCap=i.lineCap??this.lineCap,this.leadCap=i.leadCap??this.leadCap,this.tailCap=i.tailCap??this.tailCap},this.getAccumulatedRotation=()=>(this.currIteration+this.currProgress)*this.rotations*Math.PI*2,this.draw=()=>{this.parentDraw();const i=this.getAccumulatedRotation();this.drawTrack();for(let t=0;ts){this.drawContainedArc(c,u,d,x);break}else{if(l==T&&g)break;if(l==T&&!P){P=!0;const f=m[(T+1)%3];this.drawTailArcSection(c,f,x)}else if(h==T){g=!0;const f=m[T];this.drawLeadArcSection(u,f,d)}else{const f=m[T],C=m[(T+1)%3];this.drawMiddleArcSection(f,C,g)}}T=g?(T+2)%3:(T+1)%3}this.ctxDraw()}this.drawBorders()},this.drawContainedArc=(i,t,e,s)=>{const o=this.circularBezierControlPoints(i.outer,t.outer,this.origin),r=this.circularBezierControlPoints(t.inner,i.inner,this.origin);this.context.moveTo(t.inner.x,t.inner.y),this.context.bezierCurveTo(r.cp1.x,r.cp1.y,r.cp2.x,r.cp2.y,i.inner.x,i.inner.y),this.lineCap=="rounded"||this.tailCap=="rounded"?(this.ctxCircToVector(i.inner,s,i.mid),this.ctxCircToVector(s,i.outer,i.mid)):this.context.lineTo(i.outer.x,i.outer.y),this.context.bezierCurveTo(o.cp1.x,o.cp1.y,o.cp2.x,o.cp2.y,t.outer.x,t.outer.y),this.lineCap=="rounded"||this.leadCap=="rounded"?(this.ctxCircToVector(t.outer,e,t.mid),this.ctxCircToVector(e,t.inner,t.mid)):this.context.lineTo(t.inner.x,t.inner.y)},this.drawLeadArcSection=(i,t,e)=>{const s=this.circularBezierControlPoints(t.outer,i.outer,this.origin),o=this.circularBezierControlPoints(i.inner,t.inner,this.origin);this.context.bezierCurveTo(s.cp1.x,s.cp1.y,s.cp2.x,s.cp2.y,i.outer.x,i.outer.y),this.lineCap=="rounded"||this.leadCap=="rounded"?(this.ctxCircToVector(i.outer,e,i.mid),this.ctxCircToVector(e,i.inner,i.mid)):this.context.lineTo(i.inner.x,i.inner.y),this.context.bezierCurveTo(o.cp1.x,o.cp1.y,o.cp2.x,o.cp2.y,t.inner.x,t.inner.y)},this.drawMiddleArcSection=(i,t,e)=>{const s=this.circularBezierControlPoints(i.outer,t.outer,this.origin),o=this.circularBezierControlPoints(t.inner,i.inner,this.origin);e?this.context.bezierCurveTo(o.cp1.x,o.cp1.y,o.cp2.x,o.cp2.y,i.inner.x,i.inner.y):this.context.bezierCurveTo(s.cp1.x,s.cp1.y,s.cp2.x,s.cp2.y,t.outer.x,t.outer.y)},this.drawTailArcSection=(i,t,e)=>{const s=this.circularBezierControlPoints(i.outer,t.outer,this.origin),o=this.circularBezierControlPoints(t.inner,i.inner,this.origin);this.context.moveTo(t.inner.x,t.inner.y),this.context.bezierCurveTo(o.cp1.x,o.cp1.y,o.cp2.x,o.cp2.y,i.inner.x,i.inner.y),this.lineCap=="rounded"||this.tailCap=="rounded"?(this.ctxCircToVector(i.inner,e,i.mid),this.ctxCircToVector(e,i.outer,i.mid)):this.context.lineTo(i.outer.x,i.outer.y),this.context.bezierCurveTo(s.cp1.x,s.cp1.y,s.cp2.x,s.cp2.y,t.outer.x,t.outer.y)},this.drawTrack=()=>{this.trackColour&&(this.context.beginPath(),this.context.fillStyle=this.trackColour,this.context.arc(this.origin.x,this.origin.y,this.radius-1,0,Math.PI*2),this.context.arc(this.origin.x,this.origin.y,this.radius-this.arcWidth+1,0,Math.PI*2,!0),this.context.fill())},this.drawBorders=()=>{this.outerBorder&&(this.context.beginPath(),this.context.strokeStyle=this.outerBorder.colour,this.context.lineWidth=this.outerBorder.weight,this.context.arc(this.origin.x,this.origin.y,this.radius,0,Math.PI*2),this.context.stroke()),this.innerBorder&&(this.context.beginPath(),this.context.strokeStyle=this.innerBorder.colour,this.context.lineWidth=this.innerBorder.weight,this.context.arc(this.origin.x,this.origin.y,this.radius-this.arcWidth,0,Math.PI*2),this.context.stroke())},this.calculateOffsets=(i,t)=>{const e=this.radius-(this.arcs-(i+1))*this.radiusDelta*this.radius;let s,o,r;if(this.arcAnchor=="centre")s=e-t/2,o=e-this.arcWidth+t/2,r=e-t/2-(this.arcWidth-t)/2;else if(this.arcAnchor=="inner")s=e-t,o=e-this.arcWidth,r=e-t-(this.arcWidth-t)/2;else if(this.arcAnchor=="outer")s=e,o=e-(this.arcWidth-t),r=e-(this.arcWidth-t)/2;else throw new Error("Invalid arcAnchor value: "+this.arcAnchor);return s=Math.max(s,0),o=Math.max(o,0),r=Math.max(r,0),{outer:s,inner:o,mid:r}},this.calculatePositions=(i,t,e,s)=>{let o=-1;i<2*Math.PI/3?o=0:i<4*Math.PI/3?o=1:o=2;let r=-1;t<2*Math.PI/3?r=0:t<4*Math.PI/3?r=1:r=2;const u={outer:{x:this.origin.x+e.outer*Math.cos(i),y:this.origin.y+e.outer*Math.sin(i)},inner:{x:this.origin.x+e.inner*Math.cos(i),y:this.origin.y+e.inner*Math.sin(i)},mid:{x:this.origin.x+e.mid*Math.cos(i),y:this.origin.y+e.mid*Math.sin(i)}},c=(this.arcWidth-s)/2,h=i>Math.PI?c:-c,d={x:1,y:-1/Math.tan(i)},x=Math.sqrt(Math.pow(d.x,2)+Math.pow(d.y,2)),m={x:d.x/x,y:d.y/x},T={x:this.origin.x+e.mid*Math.cos(i)+m.x*h,y:this.origin.y+e.mid*Math.sin(i)+m.y*h},g={outer:{x:this.origin.x+e.outer*Math.cos(t),y:this.origin.y+e.outer*Math.sin(t)},inner:{x:this.origin.x+e.inner*Math.cos(t),y:this.origin.y+e.inner*Math.sin(t)},mid:{x:this.origin.x+e.mid*Math.cos(t),y:this.origin.y+e.mid*Math.sin(t)}},P=t{this.parentSetConfig(i),this.arcs=i?.arcs??this.arcs,this.arcWidth=i?.arcWidth??this.arcWidth,this.arcWidthDelta=i?.arcWidthDelta??this.arcWidthDelta,this.tailDelay=i?.tailDelay??this.tailDelay,this.arcDelay=i?.arcDelay??this.arcDelay,this.radius=i?.radius??this.radius,this.radiusDelta=i?.radiusDelta??this.radiusDelta,this.xOff=i?.xOff??this.xOff,this.geometries=[];for(let t=0;t{this.parentDraw();for(let i=0;i{let t=this.getProgress(this.arcDelay*i),e=this.getProgress(this.arcDelay*i-this.tailDelay);(t==1||t==0)&&(t=1e-4),(e==1||e==0)&&(e=1e-4),this.ctxSetColour(this.arcs-i-1),this.context.beginPath();const s=this.arcPoints(i),o=this.getSection(t,i),r=this.getSection(e,i);if(r==o&&t>e){this.drawSection(r,"contained",s,i),this.ctxDraw();return}let c=r;const h=this.geometries[i].checkpoints.length-2;let l=!1,d=!1;for(let x=0;x<1e3&&!(c==r&&l);x++)c==r&&!d?(this.drawSection(c,"tail",s,i),d=!0):c==o?(this.drawSection(c,"lead",s,i),l=!0):l?this.drawSection(c,"inner-mid",s,i):this.drawSection(c,"outer-mid",s,i),c=l?(c+(h-1))%h:(c+1)%h;this.ctxDraw()},this.drawPath=()=>{this.ctxSetColour(-1),this.context.beginPath(),this.context.arc(this.origin.x,this.origin.y,1,0,2*Math.PI),this.context.stroke(),this.ctxSetColour(0),this.context.beginPath(),this.context.arc(this.origin.x+this.xOff,this.origin.y,this.radius,0,2*Math.PI),this.context.stroke(),this.context.beginPath(),this.context.arc(this.origin.x-this.xOff,this.origin.y,this.radius,0,2*Math.PI),this.context.stroke();const i=this.radius*this.radius,t=this.xOff*this.xOff,e=Math.sqrt(i/(t-i)),s=e*e,o=4*t-4*(s+1)*(t-i),r=(2*this.xOff-Math.sqrt(o))/(2*(s+1)),u={x:r,y:e*r},c={x:r,y:e*r*-1};this.ctxSetColour(3),this.context.beginPath(),this.context.moveTo(this.origin.x,this.origin.y),this.context.lineTo(this.origin.x+u.x,this.origin.y+u.y),this.context.stroke(),this.ctxSetColour(4),this.context.beginPath(),this.context.moveTo(this.origin.x,this.origin.y),this.context.lineTo(this.origin.x-u.x,this.origin.y-u.y),this.context.stroke(),this.ctxSetColour(6),this.context.beginPath(),this.context.moveTo(this.origin.x,this.origin.y),this.context.lineTo(this.origin.x+c.x,this.origin.y+c.y),this.context.stroke(),this.context.beginPath(),this.context.moveTo(this.origin.x,this.origin.y),this.context.lineTo(this.origin.x-c.x,this.origin.y-c.y),this.context.stroke()},this.arcPoints=i=>{const t=this.getProgress(this.arcDelay*i),e=this.getProgress(this.arcDelay*i-this.tailDelay),s=this.progressPosition(t,i),o=this.progressPosition(e,i);return{lead:s,tail:o}},this.progressPosition=(i,t)=>{let e={x:0,y:0},s={x:0,y:0},o={x:0,y:0};const r=1-t*this.arcWidthDelta,u=this.radius-t*this.radiusDelta*this.radius;if(i<=this.geometries[t].checkpoints[1]){const h=i/this.geometries[t].checkpoints[1]*this.geometries[t].tangent_point.x*-1,l=h*this.geometries[t].k,d={x:h,y:l},x=Math.sqrt(this.arcWidth*this.arcWidth/(4*(1+this.geometries[t].k_orthogonal*this.geometries[t].k_orthogonal))),m=this.geometries[t].k_orthogonal*x;e={x:this.origin.x+d.x+x*r,y:this.origin.y+d.y+m*r},s={x:this.origin.x+h-x*r,y:this.origin.y+l-m*r},o={x:this.origin.x+h,y:this.origin.y+l}}else if(i<=this.geometries[t].checkpoints[3]){const c=(i-this.geometries[t].checkpoints[1])/(this.geometries[t].checkpoints[3]-this.geometries[t].checkpoints[1]),h=this.geometries[t].theta+c*this.geometries[t].arc_theta;o={x:this.origin.x+Math.cos(h)*u-this.xOff,y:this.origin.y+Math.sin(h)*u*-1},e={x:this.origin.x+Math.cos(h)*(u+this.arcWidth/2*r)-this.xOff,y:this.origin.y+Math.sin(h)*(u+this.arcWidth/2*r)*-1},s={x:this.origin.x+Math.cos(h)*(u-this.arcWidth/2*r)-this.xOff,y:this.origin.y+Math.sin(h)*(u-this.arcWidth/2*r)*-1}}else if(i{for(let e=0;ethis.geometries[t].checkpoints[e]&&i<=this.geometries[t].checkpoints[e+1])return e;return-1},this.drawSection=(i,t,e,s)=>{switch(i){case 0:this.draw_NW_Line(t,e,s);break;case 1:this.draw_NW_Arc(t,e,s);break;case 2:this.draw_SW_Arc(t,e,s);break;case 3:this.draw_SW_Line(t,e,s);break;case 4:this.draw_NE_Line(t,e,s);break;case 5:this.draw_NE_Arc(t,e,s);break;case 6:this.draw_SE_Arc(t,e,s);break;case 7:this.draw_SE_Line(t,e,s);break}},this.draw_NW_Line=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[0],e),o=this.progressPosition(this.geometries[e].checkpoints[1],e);switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.tail.inner);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxLineToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(o.outer);break;case"outer-mid":this.ctxLineToVector(o.outer);break;case"lead":this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(s.inner);break;case"inner-mid":this.ctxLineToVector(s.inner);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_NW_Arc=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[1],e),o=this.progressPosition(this.geometries[e].checkpoints[2],e),r={x:this.origin.x-this.xOff,y:this.origin.y};switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,t.tail.inner,r);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxCircToVector(o.inner,t.tail.inner,r),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,o.outer,r);break;case"outer-mid":this.ctxCircToVector(s.outer,o.outer,r);break;case"lead":this.ctxCircToVector(s.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,s.inner,r);break;case"inner-mid":this.ctxCircToVector(o.inner,s.inner,r);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_SW_Arc=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[2],e),o=this.progressPosition(this.geometries[e].checkpoints[3],e),r={x:this.origin.x-this.xOff,y:this.origin.y};switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,t.tail.inner,r);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxCircToVector(o.inner,t.tail.inner,r),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,o.outer,r);break;case"outer-mid":this.ctxCircToVector(s.outer,o.outer,r);break;case"lead":this.ctxCircToVector(s.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,s.inner,r);break;case"inner-mid":this.ctxCircToVector(o.inner,s.inner,r);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_SW_Line=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[3],e),o=this.progressPosition(this.geometries[e].checkpoints[4],e);switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.tail.inner);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxLineToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(o.outer);break;case"outer-mid":this.ctxLineToVector(o.outer);break;case"lead":this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(s.inner);break;case"inner-mid":this.ctxLineToVector(s.inner);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_NE_Line=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[4],e),o=this.progressPosition(this.geometries[e].checkpoints[5],e);switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.tail.inner);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxLineToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(o.outer);break;case"outer-mid":this.ctxLineToVector(o.outer);break;case"lead":this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(s.inner);break;case"inner-mid":this.ctxLineToVector(s.inner);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_NE_Arc=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[5],e),o=this.progressPosition(this.geometries[e].checkpoints[6],e),r={x:this.origin.x+this.xOff,y:this.origin.y};switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,t.tail.inner,r);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxCircToVector(o.inner,t.tail.inner,r),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,o.outer,r);break;case"outer-mid":this.ctxCircToVector(s.outer,o.outer,r);break;case"lead":this.ctxCircToVector(s.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,s.inner,r);break;case"inner-mid":this.ctxCircToVector(o.inner,s.inner,r);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_SE_Arc=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[6],e),o=this.progressPosition(this.geometries[e].checkpoints[7],e),r={x:this.origin.x+this.xOff,y:this.origin.y};switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,t.tail.inner,r);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxCircToVector(o.inner,t.tail.inner,r),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,o.outer,r);break;case"outer-mid":this.ctxCircToVector(s.outer,o.outer,r);break;case"lead":this.ctxCircToVector(s.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,s.inner,r);break;case"inner-mid":this.ctxCircToVector(o.inner,s.inner,r);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_SE_Line=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[7],e),o=this.progressPosition(this.geometries[e].checkpoints[8],e);switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.tail.inner);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxLineToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(o.outer),this.ctxMoveToVector(o.inner);break;case"outer-mid":this.ctxLineToVector(o.inner);break;case"lead":this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(s.inner);break;case"inner-mid":this.ctxLineToVector(s.inner);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.arcs=1,this.arcWidth=10,this.arcWidthDelta=0,this.tailDelay=.2,this.arcDelay=.1;const a=Math.min(this.canvas.width,this.canvas.height,n?.canvasHeight??1/0,n?.canvasWidth??1/0);this.radius=a/8,this.radiusDelta=0,this.xOff=this.radius*2,this.geometries=[];for(let i=0;i{this.parentSetConfig(t),this.sideLength=t?.sideLength??this.sideLength,this.circleSize=t?.circleSize??this.circleSize,this.relativeExpansion=t?.relativeExpansion??this.relativeExpansion,this.delay=t?.delay??this.delay,this.alternateSpin=t?.alternateSpin??this.alternateSpin,this.drawStyle=t?.drawStyle??this.drawStyle,this.rotations=t?.rotations??this.rotations,this.opacityPulse=t?.opacityPulse??this.opacityPulse,this.radiusPulse=t?.radiusPulse??this.radiusPulse},this.draw=()=>{this.parentDraw();for(let t=this.sideLength-1;t>=0;t--){let e=this.getProgress(this.delay*t)*Math.PI*2*this.rotations;this.alternateSpin&&t%2==0&&(e*=-1),this.ctxSetColour(t),this.performOpacityPulse(t);const s=this.performRadiusPulse(t);for(let o=0;o<6;o++){const r=Math.PI/6+Math.PI/3*o,u=this.circleSize*this.relativeExpansion*t,c={x:this.origin.x+u*Math.cos(r+e),y:this.origin.y+u*Math.sin(r+e)};if(this.context.beginPath(),this.context.arc(c.x,c.y,s,0,Math.PI*2),this.ctxDraw(),t==0)break;for(let h=0;h{const e=t;if(this.opacityPulse.style=="coelesce"){const s=this.getProgressLinear(this.opacityPulse.delay*e);this.ctxModifyOpacity(s<.5?-(s*2):-2+s*2)}else if(this.opacityPulse.style=="disperse"){const s=this.getProgressLinear(this.opacityPulse.delay*(this.sideLength-1-e));this.ctxModifyOpacity(s<.5?-(s*2):-2+s*2)}},this.performRadiusPulse=t=>{const e=t;let s=this.circleSize;if(this.radiusPulse.style=="coelesce"){const o=this.getProgressLinear(this.radiusPulse.delay*e),r=o<.5?-(o*2):-2+o*2;s=s+r*this.radiusPulse.intensity*s}else if(this.radiusPulse.style=="disperse"){const o=this.getProgressLinear(this.radiusPulse.delay*(this.sideLength-1-e)),r=o<.5?-(o*2):-2+o*2;s=s+r*this.radiusPulse.intensity*s}return s};const a={style:"off",delay:.1,intensity:1};this.sideLength=3;const i=Math.min(this.canvas.width,this.canvas.height,n?.canvasHeight??1/0,n?.canvasWidth??1/0);this.circleSize=i/8,this.relativeExpansion=1,this.delay=.1,this.alternateSpin=!1,this.drawStyle="stroke",this.rotations=1,this.opacityPulse=structuredClone(a),this.radiusPulse=structuredClone(a),n&&this.setConfig(n),this.postConstructor()}}try{new D(""),new b(""),new _("")}catch{console.log("If you know a better way to not do this please let me know")} +(function(){const y=document.createElement("link").relList;if(y&&y.supports&&y.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))a(i);new MutationObserver(i=>{for(const t of i)if(t.type==="childList")for(const e of t.addedNodes)e.tagName==="LINK"&&e.rel==="modulepreload"&&a(e)}).observe(document,{childList:!0,subtree:!0});function n(i){const t={};return i.integrity&&(t.integrity=i.integrity),i.referrerPolicy&&(t.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?t.credentials="include":i.crossOrigin==="anonymous"?t.credentials="omit":t.credentials="same-origin",t}function a(i){if(i.ep)return;i.ep=!0;const t=n(i);fetch(i.href,t)}})();const k=(w,y)=>(w%y+y)%y,S=()=>"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,w=>{const y=Math.floor(Math.random()*16);return(w=="x"?y:y&3|8).toString(16)});class V{constructor(y){if(this.postConstructor=()=>{this.postConstructorCalls++,this.paused||requestAnimationFrame(this.animate)},this.setConfig=n=>{this.backgroundColour=n.backgroundColour??this.backgroundColour,this.currProgress=n.currProgress??this.currProgress,this.lastProgress=n.lastProgress??this.lastProgress,this.rest=n.rest??this.rest,this.fps=n.fps??this.fps,this.cycleDuration_ms=n.cycleDuration_ms??this.cycleDuration_ms,this.currIteration=n.currIteration??this.currIteration,this.nIterations=n.nIterations??this.nIterations,this.paused=n.paused??this.paused,this.colours=n.colours??this.colours,this.opacity=n.opacity??this.opacity,this.opacityDelta=n.opacityDelta??this.opacityDelta,this.timingFunction=n.timingFunction??this.timingFunction,this.customTimingFunction=n.customTimingFunction??this.customTimingFunction,this.drawStyle=n.drawStyle??this.drawStyle,this.canvas.width=n.canvasWidth??this.canvas.width,this.canvas.height=n.canvasHeight??this.canvas.height,this.origin={x:Math.floor(this.canvas.width/2),y:Math.floor(this.canvas.height/2)}},this.draw=()=>{this.context.clearRect(0,0,this.canvas.width,this.canvas.height);const a=1e3/this.fps/this.cycleDuration_ms;this.frame=Math.floor(this.currProgress/a),this.lastDraw=performance.now(),this.backgroundColour!=null&&(this.context.fillStyle=this.backgroundColour,this.context.fillRect(0,0,this.canvas.width,this.canvas.height))},this.step=()=>{this.seek(1)},this.seek=n=>{const i=1e3/this.fps/this.cycleDuration_ms;this.lastProgress=this.currProgress,this.currProgress=(1+this.currProgress+n*i)%1,this.lastProgress===1&&(this.currProgress=0),this.draw()},this.animate=()=>{if(this.paused)return;requestAnimationFrame(this.animate);const n=performance.now(),a=n-this.lastDraw,i=1e3/this.fps;athis.currProgress&&(this.currIteration++,this.currIteration>=this.nIterations&&this.pause()),this.draw())},this.getProgress=n=>{switch(this.timingFunction){case"sinusoidal":return this.getProgressSinusoidal(n);case"quadratic":return this.getProgressExponential(2,n);case"cubic":return this.getProgressExponential(3,n);case"custom":if(this.customTimingFunction==null)throw new Error("Custom timing function does not exist.");return this.customTimingFunction(n);default:return this.getProgressLinear(n)}},this.getProgressLinear=n=>{const a=n?(this.currProgress+1+n)%1:this.currProgress;return Math.min(1,a/(1-this.rest))},this.getProgressExponential=(n,a)=>{const i=a?(this.currProgress+1+a)%1:this.currProgress,t=Math.min(1,i/(1-this.rest));return Math.pow(t,n)},this.getProgressSinusoidal=n=>{const a=n?(this.currProgress+1+n)%1:this.currProgress,i=Math.min(1,a/(1-this.rest));return .5+Math.sin((i-.5)*Math.PI)/2},this.play=()=>{if(!this.paused)return;this.paused=!1;const n=performance.now();this.lastDraw=n,this.pauseDuration+=n-this.pauseTimestamp,requestAnimationFrame(this.animate)},this.pause=()=>{this.paused||(this.paused=!0,this.pauseTimestamp=performance.now())},this.ctxDraw=()=>{this.drawStyle=="fill"?this.context.fill():this.context.stroke()},this.ctxMoveToVector=n=>{this.context.moveTo(n.x,n.y)},this.ctxLineToVector=n=>{this.context.lineTo(n.x,n.y)},this.ctxCircToVector=(n,a,i)=>{const t=this.circularBezierControlPoints(n,a,i);this.context.bezierCurveTo(t.cp1.x,t.cp1.y,t.cp2.x,t.cp2.y,a.x,a.y)},this.ctxSetColour=n=>{const a=k(n,this.colours.length),t=Math.floor(Math.max(0,this.opacity-(this.colours.length-1-a)*this.opacityDelta)*255).toString(16).padStart(2,"0"),e=`${this.colours[a]}${t}`;this.context.strokeStyle=e,this.context.fillStyle=e,this.currColour=e},this.ctxModifyOpacity=n=>{const a=this.currColour,i=a.slice(0,7),t=a.slice(7,9),e=parseInt(t,16),o=Math.floor(e+e*n).toString(16).padStart(2,"0"),r=`${i}${o}`;this.context.strokeStyle=r,this.context.fillStyle=r,this.currColour=r},this.drawDot=n=>{this.context.beginPath(),this.context.arc(this.origin.x+n.x,this.origin.y+n.y,2,0,2*Math.PI),this.context.fill()},this.circularBezierControlPoints=(n,a,i)=>{const t=i??{x:0,y:0},e=n.x-t.x,s=n.y-t.y,o=a.x-t.x,r=a.y-t.y,u=e*e+s*s,c=u+e*o+s*r,h=4/3*(Math.sqrt(2*u*c)-c)/(e*r-s*o),l=t.x+e-h*s,d=t.y+s+h*e,x=t.x+o+h*r,m=t.y+r-h*o;return{cp1:{x:l,y:d},cp2:{x,y:m}}},window.isSecureContext?this.id=crypto.randomUUID():this.id=S(),this.postConstructorCalls=0,this.start=performance.now(),this.lastDraw=this.start,this.lastMutationTimestamp=this.start,this.pauseTimestamp=0,this.pauseDuration=0,this.canvas=document.getElementById(y),this.canvas===null)throw new Error("Canvas element not found with id: "+y);this.canvas.setAttribute("data-animautomata-id",this.id),this.origin={x:Math.floor(this.canvas.width/2),y:Math.floor(this.canvas.height/2)},this.currColour="",this.context=this.canvas.getContext("2d"),this.frame=0,this.backgroundColour=null,this.currProgress=0,this.lastProgress=0,this.rest=0,this.fps=60,this.cycleDuration_ms=1500,this.currIteration=0,this.nIterations=1/0,this.paused=!1,this.colours=["#000000"],this.opacity=1,this.opacityDelta=0,this.timingFunction="sinusoidal",this.customTimingFunction=this.getProgressLinear,this.drawStyle="fill"}}class D extends V{constructor(y,n){super(y),this.parentDraw=this.draw,this.parentSetConfig=this.setConfig,this.setConfig=i=>{this.parentSetConfig(i),this.arcs=i.arcs??this.arcs,this.arcWidth=i.arcWidth??this.arcWidth,this.arcWidthDelta=i.arcWidthDelta??this.arcWidthDelta,this.arcAnchor=i.arcAnchor??this.arcAnchor,this.tailDelay=i.tailDelay??this.tailDelay,this.arcDelay=i.arcDelay??this.arcDelay,this.radius=i.radius??this.radius,this.radiusDelta=i.radiusDelta??this.radiusDelta,this.rotations=i.rotations??this.rotations,this.innerBorder=i.innerBorder??this.innerBorder,this.outerBorder=i.outerBorder??this.outerBorder,this.trackColour=i.trackColour??this.trackColour,this.lineCap=i.lineCap??this.lineCap,this.leadCap=i.leadCap??this.leadCap,this.tailCap=i.tailCap??this.tailCap},this.getAccumulatedRotation=()=>(this.currIteration+this.currProgress)*this.rotations*Math.PI*2,this.draw=()=>{this.parentDraw();const i=this.getAccumulatedRotation();this.drawTrack();for(let t=0;ts){this.drawContainedArc(c,u,d,x);break}else{if(l==T&&g)break;if(l==T&&!P){P=!0;const f=m[(T+1)%3];this.drawTailArcSection(c,f,x)}else if(h==T){g=!0;const f=m[T];this.drawLeadArcSection(u,f,d)}else{const f=m[T],C=m[(T+1)%3];this.drawMiddleArcSection(f,C,g)}}T=g?(T+2)%3:(T+1)%3}this.ctxDraw()}this.drawBorders()},this.drawContainedArc=(i,t,e,s)=>{const o=this.circularBezierControlPoints(i.outer,t.outer,this.origin),r=this.circularBezierControlPoints(t.inner,i.inner,this.origin);this.context.moveTo(t.inner.x,t.inner.y),this.context.bezierCurveTo(r.cp1.x,r.cp1.y,r.cp2.x,r.cp2.y,i.inner.x,i.inner.y),this.lineCap=="rounded"||this.tailCap=="rounded"?(this.ctxCircToVector(i.inner,s,i.mid),this.ctxCircToVector(s,i.outer,i.mid)):this.context.lineTo(i.outer.x,i.outer.y),this.context.bezierCurveTo(o.cp1.x,o.cp1.y,o.cp2.x,o.cp2.y,t.outer.x,t.outer.y),this.lineCap=="rounded"||this.leadCap=="rounded"?(this.ctxCircToVector(t.outer,e,t.mid),this.ctxCircToVector(e,t.inner,t.mid)):this.context.lineTo(t.inner.x,t.inner.y)},this.drawLeadArcSection=(i,t,e)=>{const s=this.circularBezierControlPoints(t.outer,i.outer,this.origin),o=this.circularBezierControlPoints(i.inner,t.inner,this.origin);this.context.bezierCurveTo(s.cp1.x,s.cp1.y,s.cp2.x,s.cp2.y,i.outer.x,i.outer.y),this.lineCap=="rounded"||this.leadCap=="rounded"?(this.ctxCircToVector(i.outer,e,i.mid),this.ctxCircToVector(e,i.inner,i.mid)):this.context.lineTo(i.inner.x,i.inner.y),this.context.bezierCurveTo(o.cp1.x,o.cp1.y,o.cp2.x,o.cp2.y,t.inner.x,t.inner.y)},this.drawMiddleArcSection=(i,t,e)=>{const s=this.circularBezierControlPoints(i.outer,t.outer,this.origin),o=this.circularBezierControlPoints(t.inner,i.inner,this.origin);e?this.context.bezierCurveTo(o.cp1.x,o.cp1.y,o.cp2.x,o.cp2.y,i.inner.x,i.inner.y):this.context.bezierCurveTo(s.cp1.x,s.cp1.y,s.cp2.x,s.cp2.y,t.outer.x,t.outer.y)},this.drawTailArcSection=(i,t,e)=>{const s=this.circularBezierControlPoints(i.outer,t.outer,this.origin),o=this.circularBezierControlPoints(t.inner,i.inner,this.origin);this.context.moveTo(t.inner.x,t.inner.y),this.context.bezierCurveTo(o.cp1.x,o.cp1.y,o.cp2.x,o.cp2.y,i.inner.x,i.inner.y),this.lineCap=="rounded"||this.tailCap=="rounded"?(this.ctxCircToVector(i.inner,e,i.mid),this.ctxCircToVector(e,i.outer,i.mid)):this.context.lineTo(i.outer.x,i.outer.y),this.context.bezierCurveTo(s.cp1.x,s.cp1.y,s.cp2.x,s.cp2.y,t.outer.x,t.outer.y)},this.drawTrack=()=>{this.trackColour&&(this.context.beginPath(),this.context.fillStyle=this.trackColour,this.context.arc(this.origin.x,this.origin.y,this.radius-1,0,Math.PI*2),this.context.arc(this.origin.x,this.origin.y,this.radius-this.arcWidth+1,0,Math.PI*2,!0),this.context.fill())},this.drawBorders=()=>{this.outerBorder&&(this.context.beginPath(),this.context.strokeStyle=this.outerBorder.colour,this.context.lineWidth=this.outerBorder.weight,this.context.arc(this.origin.x,this.origin.y,this.radius,0,Math.PI*2),this.context.stroke()),this.innerBorder&&(this.context.beginPath(),this.context.strokeStyle=this.innerBorder.colour,this.context.lineWidth=this.innerBorder.weight,this.context.arc(this.origin.x,this.origin.y,this.radius-this.arcWidth,0,Math.PI*2),this.context.stroke())},this.calculateOffsets=(i,t)=>{const e=this.radius-(this.arcs-(i+1))*this.radiusDelta*this.radius;let s,o,r;if(this.arcAnchor=="centre")s=e-t/2,o=e-this.arcWidth+t/2,r=e-t/2-(this.arcWidth-t)/2;else if(this.arcAnchor=="inner")s=e-t,o=e-this.arcWidth,r=e-t-(this.arcWidth-t)/2;else if(this.arcAnchor=="outer")s=e,o=e-(this.arcWidth-t),r=e-(this.arcWidth-t)/2;else throw new Error("Invalid arcAnchor value: "+this.arcAnchor);return s=Math.max(s,0),o=Math.max(o,0),r=Math.max(r,0),{outer:s,inner:o,mid:r}},this.calculatePositions=(i,t,e,s)=>{let o=-1;i<2*Math.PI/3?o=0:i<4*Math.PI/3?o=1:o=2;let r=-1;t<2*Math.PI/3?r=0:t<4*Math.PI/3?r=1:r=2;const u={outer:{x:this.origin.x+e.outer*Math.cos(i),y:this.origin.y+e.outer*Math.sin(i)},inner:{x:this.origin.x+e.inner*Math.cos(i),y:this.origin.y+e.inner*Math.sin(i)},mid:{x:this.origin.x+e.mid*Math.cos(i),y:this.origin.y+e.mid*Math.sin(i)}},c=(this.arcWidth-s)/2,h=i>Math.PI?c:-c,d={x:1,y:-1/Math.tan(i)},x=Math.sqrt(Math.pow(d.x,2)+Math.pow(d.y,2)),m={x:d.x/x,y:d.y/x},T={x:this.origin.x+e.mid*Math.cos(i)+m.x*h,y:this.origin.y+e.mid*Math.sin(i)+m.y*h},g={outer:{x:this.origin.x+e.outer*Math.cos(t),y:this.origin.y+e.outer*Math.sin(t)},inner:{x:this.origin.x+e.inner*Math.cos(t),y:this.origin.y+e.inner*Math.sin(t)},mid:{x:this.origin.x+e.mid*Math.cos(t),y:this.origin.y+e.mid*Math.sin(t)}},P=t{this.parentSetConfig(i),this.arcs=i?.arcs??this.arcs,this.arcWidth=i?.arcWidth??this.arcWidth,this.arcWidthDelta=i?.arcWidthDelta??this.arcWidthDelta,this.tailDelay=i?.tailDelay??this.tailDelay,this.arcDelay=i?.arcDelay??this.arcDelay,this.radius=i?.radius??this.radius,this.radiusDelta=i?.radiusDelta??this.radiusDelta,this.xOff=i?.xOff??this.xOff,this.geometries=[];for(let t=0;t{this.parentDraw();for(let i=0;i{let t=this.getProgress(this.arcDelay*i),e=this.getProgress(this.arcDelay*i-this.tailDelay);(t==1||t==0)&&(t=1e-4),(e==1||e==0)&&(e=1e-4),this.ctxSetColour(this.arcs-i-1),this.context.beginPath();const s=this.arcPoints(i),o=this.getSection(t,i),r=this.getSection(e,i);if(r==o&&t>e){this.drawSection(r,"contained",s,i),this.ctxDraw();return}let c=r;const h=this.geometries[i].checkpoints.length-2;let l=!1,d=!1;for(let x=0;x<1e3&&!(c==r&&l);x++)c==r&&!d?(this.drawSection(c,"tail",s,i),d=!0):c==o?(this.drawSection(c,"lead",s,i),l=!0):l?this.drawSection(c,"inner-mid",s,i):this.drawSection(c,"outer-mid",s,i),c=l?(c+(h-1))%h:(c+1)%h;this.ctxDraw()},this.drawPath=()=>{this.ctxSetColour(-1),this.context.beginPath(),this.context.arc(this.origin.x,this.origin.y,1,0,2*Math.PI),this.context.stroke(),this.ctxSetColour(0),this.context.beginPath(),this.context.arc(this.origin.x+this.xOff,this.origin.y,this.radius,0,2*Math.PI),this.context.stroke(),this.context.beginPath(),this.context.arc(this.origin.x-this.xOff,this.origin.y,this.radius,0,2*Math.PI),this.context.stroke();const i=this.radius*this.radius,t=this.xOff*this.xOff,e=Math.sqrt(i/(t-i)),s=e*e,o=4*t-4*(s+1)*(t-i),r=(2*this.xOff-Math.sqrt(o))/(2*(s+1)),u={x:r,y:e*r},c={x:r,y:e*r*-1};this.ctxSetColour(3),this.context.beginPath(),this.context.moveTo(this.origin.x,this.origin.y),this.context.lineTo(this.origin.x+u.x,this.origin.y+u.y),this.context.stroke(),this.ctxSetColour(4),this.context.beginPath(),this.context.moveTo(this.origin.x,this.origin.y),this.context.lineTo(this.origin.x-u.x,this.origin.y-u.y),this.context.stroke(),this.ctxSetColour(6),this.context.beginPath(),this.context.moveTo(this.origin.x,this.origin.y),this.context.lineTo(this.origin.x+c.x,this.origin.y+c.y),this.context.stroke(),this.context.beginPath(),this.context.moveTo(this.origin.x,this.origin.y),this.context.lineTo(this.origin.x-c.x,this.origin.y-c.y),this.context.stroke()},this.arcPoints=i=>{const t=this.getProgress(this.arcDelay*i),e=this.getProgress(this.arcDelay*i-this.tailDelay),s=this.progressPosition(t,i),o=this.progressPosition(e,i);return{lead:s,tail:o}},this.progressPosition=(i,t)=>{let e={x:0,y:0},s={x:0,y:0},o={x:0,y:0};const r=1-t*this.arcWidthDelta,u=this.radius-t*this.radiusDelta*this.radius;if(i<=this.geometries[t].checkpoints[1]){const h=i/this.geometries[t].checkpoints[1]*this.geometries[t].tangent_point.x*-1,l=h*this.geometries[t].k,d={x:h,y:l},x=Math.sqrt(this.arcWidth*this.arcWidth/(4*(1+this.geometries[t].k_orthogonal*this.geometries[t].k_orthogonal))),m=this.geometries[t].k_orthogonal*x;e={x:this.origin.x+d.x+x*r,y:this.origin.y+d.y+m*r},s={x:this.origin.x+h-x*r,y:this.origin.y+l-m*r},o={x:this.origin.x+h,y:this.origin.y+l}}else if(i<=this.geometries[t].checkpoints[3]){const c=(i-this.geometries[t].checkpoints[1])/(this.geometries[t].checkpoints[3]-this.geometries[t].checkpoints[1]),h=this.geometries[t].theta+c*this.geometries[t].arc_theta;o={x:this.origin.x+Math.cos(h)*u-this.xOff,y:this.origin.y+Math.sin(h)*u*-1},e={x:this.origin.x+Math.cos(h)*(u+this.arcWidth/2*r)-this.xOff,y:this.origin.y+Math.sin(h)*(u+this.arcWidth/2*r)*-1},s={x:this.origin.x+Math.cos(h)*(u-this.arcWidth/2*r)-this.xOff,y:this.origin.y+Math.sin(h)*(u-this.arcWidth/2*r)*-1}}else if(i{for(let e=0;ethis.geometries[t].checkpoints[e]&&i<=this.geometries[t].checkpoints[e+1])return e;return-1},this.drawSection=(i,t,e,s)=>{switch(i){case 0:this.draw_NW_Line(t,e,s);break;case 1:this.draw_NW_Arc(t,e,s);break;case 2:this.draw_SW_Arc(t,e,s);break;case 3:this.draw_SW_Line(t,e,s);break;case 4:this.draw_NE_Line(t,e,s);break;case 5:this.draw_NE_Arc(t,e,s);break;case 6:this.draw_SE_Arc(t,e,s);break;case 7:this.draw_SE_Line(t,e,s);break}},this.draw_NW_Line=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[0],e),o=this.progressPosition(this.geometries[e].checkpoints[1],e);switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.tail.inner);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxLineToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(o.outer);break;case"outer-mid":this.ctxLineToVector(o.outer);break;case"lead":this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(s.inner);break;case"inner-mid":this.ctxLineToVector(s.inner);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_NW_Arc=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[1],e),o=this.progressPosition(this.geometries[e].checkpoints[2],e),r={x:this.origin.x-this.xOff,y:this.origin.y};switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,t.tail.inner,r);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxCircToVector(o.inner,t.tail.inner,r),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,o.outer,r);break;case"outer-mid":this.ctxCircToVector(s.outer,o.outer,r);break;case"lead":this.ctxCircToVector(s.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,s.inner,r);break;case"inner-mid":this.ctxCircToVector(o.inner,s.inner,r);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_SW_Arc=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[2],e),o=this.progressPosition(this.geometries[e].checkpoints[3],e),r={x:this.origin.x-this.xOff,y:this.origin.y};switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,t.tail.inner,r);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxCircToVector(o.inner,t.tail.inner,r),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,o.outer,r);break;case"outer-mid":this.ctxCircToVector(s.outer,o.outer,r);break;case"lead":this.ctxCircToVector(s.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,s.inner,r);break;case"inner-mid":this.ctxCircToVector(o.inner,s.inner,r);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_SW_Line=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[3],e),o=this.progressPosition(this.geometries[e].checkpoints[4],e);switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.tail.inner);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxLineToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(o.outer);break;case"outer-mid":this.ctxLineToVector(o.outer);break;case"lead":this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(s.inner);break;case"inner-mid":this.ctxLineToVector(s.inner);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_NE_Line=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[4],e),o=this.progressPosition(this.geometries[e].checkpoints[5],e);switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.tail.inner);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxLineToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(o.outer);break;case"outer-mid":this.ctxLineToVector(o.outer);break;case"lead":this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(s.inner);break;case"inner-mid":this.ctxLineToVector(s.inner);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_NE_Arc=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[5],e),o=this.progressPosition(this.geometries[e].checkpoints[6],e),r={x:this.origin.x+this.xOff,y:this.origin.y};switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,t.tail.inner,r);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxCircToVector(o.inner,t.tail.inner,r),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,o.outer,r);break;case"outer-mid":this.ctxCircToVector(s.outer,o.outer,r);break;case"lead":this.ctxCircToVector(s.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,s.inner,r);break;case"inner-mid":this.ctxCircToVector(o.inner,s.inner,r);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_SE_Arc=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[6],e),o=this.progressPosition(this.geometries[e].checkpoints[7],e),r={x:this.origin.x+this.xOff,y:this.origin.y};switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,t.tail.inner,r);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxCircToVector(o.inner,t.tail.inner,r),this.ctxLineToVector(t.tail.outer),this.ctxCircToVector(t.tail.outer,o.outer,r);break;case"outer-mid":this.ctxCircToVector(s.outer,o.outer,r);break;case"lead":this.ctxCircToVector(s.outer,t.lead.outer,r),this.ctxLineToVector(t.lead.inner),this.ctxCircToVector(t.lead.inner,s.inner,r);break;case"inner-mid":this.ctxCircToVector(o.inner,s.inner,r);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.draw_SE_Line=(i,t,e)=>{const s=this.progressPosition(this.geometries[e].checkpoints[7],e),o=this.progressPosition(this.geometries[e].checkpoints[8],e);switch(i){case"contained":this.ctxMoveToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.tail.inner);break;case"tail":this.ctxMoveToVector(o.inner),this.ctxLineToVector(t.tail.inner),this.ctxLineToVector(t.tail.outer),this.ctxLineToVector(o.outer),this.ctxMoveToVector(o.inner);break;case"outer-mid":this.ctxLineToVector(o.inner);break;case"lead":this.ctxLineToVector(t.lead.inner),this.ctxLineToVector(t.lead.outer),this.ctxLineToVector(s.inner);break;case"inner-mid":this.ctxLineToVector(s.inner);break;default:console.error("Tried to draw section with invalid order: "+i)}},this.arcs=1,this.arcWidth=10,this.arcWidthDelta=0,this.tailDelay=.2,this.arcDelay=.1;const a=Math.min(this.canvas.width,this.canvas.height,n?.canvasHeight??1/0,n?.canvasWidth??1/0);this.radius=a/8,this.radiusDelta=0,this.xOff=this.radius*2,this.geometries=[];for(let i=0;i{this.parentSetConfig(t),this.sideLength=t?.sideLength??this.sideLength,this.circleSize=t?.circleSize??this.circleSize,this.relativeExpansion=t?.relativeExpansion??this.relativeExpansion,this.delay=t?.delay??this.delay,this.alternateSpin=t?.alternateSpin??this.alternateSpin,this.drawStyle=t?.drawStyle??this.drawStyle,this.rotations=t?.rotations??this.rotations,this.opacityPulse=t?.opacityPulse??this.opacityPulse,this.radiusPulse=t?.radiusPulse??this.radiusPulse},this.draw=()=>{this.parentDraw();for(let t=this.sideLength-1;t>=0;t--){let e=this.getProgress(this.delay*t)*Math.PI*2*this.rotations;this.alternateSpin&&t%2==0&&(e*=-1),this.ctxSetColour(t),this.performOpacityPulse(t);const s=this.performRadiusPulse(t);for(let o=0;o<6;o++){const r=Math.PI/6+Math.PI/3*o,u=this.circleSize*this.relativeExpansion*t,c={x:this.origin.x+u*Math.cos(r+e),y:this.origin.y+u*Math.sin(r+e)};if(this.context.beginPath(),this.context.arc(c.x,c.y,s,0,Math.PI*2),this.ctxDraw(),t==0)break;for(let h=0;h{const e=t;if(this.opacityPulse.style=="coelesce"){const s=this.getProgressLinear(this.opacityPulse.delay*e);this.ctxModifyOpacity(s<.5?-(s*2):-2+s*2)}else if(this.opacityPulse.style=="disperse"){const s=this.getProgressLinear(this.opacityPulse.delay*(this.sideLength-1-e));this.ctxModifyOpacity(s<.5?-(s*2):-2+s*2)}},this.performRadiusPulse=t=>{const e=t;let s=this.circleSize;if(this.radiusPulse.style=="coelesce"){const o=this.getProgressLinear(this.radiusPulse.delay*e),r=o<.5?-(o*2):-2+o*2;s=s+r*this.radiusPulse.intensity*s}else if(this.radiusPulse.style=="disperse"){const o=this.getProgressLinear(this.radiusPulse.delay*(this.sideLength-1-e)),r=o<.5?-(o*2):-2+o*2;s=s+r*this.radiusPulse.intensity*s}return s};const a={style:"off",delay:.1,intensity:1};this.sideLength=3;const i=Math.min(this.canvas.width,this.canvas.height,n?.canvasHeight??1/0,n?.canvasWidth??1/0);this.circleSize=i/8,this.relativeExpansion=1,this.delay=.1,this.alternateSpin=!1,this.drawStyle="stroke",this.rotations=1,this.opacityPulse=structuredClone(a),this.radiusPulse=structuredClone(a),n&&this.setConfig(n),this.postConstructor()}}console.log("Loading animautomata library.");window.Antiquum=D;window.Lemniscate=b;window.Sempiternal=_; diff --git a/index.ts b/index.ts index 22c5a35..c013291 100644 --- a/index.ts +++ b/index.ts @@ -1,12 +1,10 @@ import { Antiquum, Lemniscate, Sempiternal } from "./src"; -try { - new Antiquum(""); - new Lemniscate(""); - new Sempiternal(""); -} catch (e) { - console.log("If you know a better way to not do this please let me know"); -} - -// Not sure this is the best way to get vite to actually output the source code to ./dist -// But it works? +// Not sure if this is the ideal way to do this? +console.log("Loading animautomata library."); +// @ts-expect-error +window.Antiquum = Antiquum; +// @ts-expect-error +window.Lemniscate = Lemniscate; +// @ts-expect-error +window.Sempiternal = Sempiternal; diff --git a/package.json b/package.json index 930a91f..2cc90dc 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "animautomata", - "version": "1.0.4", + "version": "1.0.5", "description": "a library for creating high quality loading animations using the Canvas API", "main": "src/index.ts", "type": "module", "scripts": { "dev": "vite", "test": "jest", - "build": "npm run docs && vite build && vite build --mode examples", + "build": "vite build && vite build --mode examples", "preview": "vite preview", "docs": "typedoc src/index.ts --plugin typedoc-material-theme --themeColor '#c70039' --out public/docs" }, diff --git a/public/docs/index.html b/public/docs/index.html index 428a3fe..6934315 100644 --- a/public/docs/index.html +++ b/public/docs/index.html @@ -1,200 +1,654 @@ -animautomata

animautomata

Animautomata

An open-source, zero-dependency, fully-typed solution for creating high-quality, lightweight loading animations that fit your brand identity, using the Canvas API.

-
    -
  • Fully-typed (source written in Typescript).
  • -
  • Zero-dependency.
  • -
  • Add, transform, and remove loading animations with one line of javascript.
  • -
  • Simple but deeply configurable API.
  • -
  • Create and experiment using the Animautomata Forge web GUI
  • -
  • Plug-and-play React components are available with animautomata-react.
  • -
  • No image files => faster loading. The minified library size is ~30kb uncompressed (~6kb gzipped). For comparison the first google image result for "loading animation gif" is over 80kb.
  • -
  • Use the abstract Animautomata parent class to create your own custom presets.
  • -
-

Animautomata Forge

-

https://era-epoch.github.io/animautomata/docs/

-

https://era-epoch.github.io/animautomata/examples/

-

with source code:

-

https://github.com/era-epoch/animautomata/blob/main/examples/examples.ts

-

via npm

-

npm install --save animautomata

-

via unpkg cdn

-

<script src="https://unpkg.com/animautomata@latest/dist/min.js></script>

-

via jsdeliver cdn

-

<script src="https://cdn.jsdelivr.net/npm/animautomata@latest/dist/min.js"></script>

-

via git

-

git clone https://github.com/era-epoch/animautomata.git

-

This project was created using typescript, distributed via npm, developed with vite, tested with jest, and has documentation created with typedoc.

-

MIT

-
+ @media (prefers-color-scheme: light) { + :root { + --md-sys-color-primary: #be0036; + --md-sys-color-on-primary: #ffffff; + --md-sys-color-primary-container: #ffdada; + --md-sys-color-on-primary-container: #40000c; + --md-sys-color-secondary: #765657; + --md-sys-color-on-secondary: #ffffff; + --md-sys-color-secondary-container: #ffdada; + --md-sys-color-on-secondary-container: #2c1516; + --md-sys-color-tertiary: #76592f; + --md-sys-color-on-tertiary: #ffffff; + --md-sys-color-tertiary-container: #ffddb2; + --md-sys-color-on-tertiary-container: #291800; + --md-sys-color-error: #ba1a1a; + --md-sys-color-on-error: #ffffff; + --md-sys-color-error-container: #ffdad6; + --md-sys-color-on-error-container: #410002; + --md-sys-color-background: #fffbff; + --md-sys-color-on-background: #201a1a; + --md-sys-color-surface: #fffbff; + --md-sys-color-on-surface: #201a1a; + --md-sys-color-surface-variant: #f4dddd; + --md-sys-color-on-surface-variant: #524343; + --md-sys-color-outline: #857373; + --md-sys-color-outline-variant: #d7c1c1; + --md-sys-color-shadow: #000000; + --md-sys-color-scrim: #000000; + --md-sys-color-inverse-surface: #362f2f; + --md-sys-color-inverse-on-surface: #fbeeed; + --md-sys-color-inverse-primary: #ffb3b6; + --md-sys-color-surface-dim: #e4d7d7; + --md-sys-color-surface-bright: #fff8f7; + --md-sys-color-surface-container-lowest: #ffffff; + --md-sys-color-surface-container-low: #fef1f0; + --md-sys-color-surface-container: #f8ebea; + --md-sys-color-surface-container-high: #f2e5e5; + --md-sys-color-surface-container-highest: #ece0df; + } + } + :root[data-theme="light"] { + --md-sys-color-primary: #be0036; + --md-sys-color-on-primary: #ffffff; + --md-sys-color-primary-container: #ffdada; + --md-sys-color-on-primary-container: #40000c; + --md-sys-color-secondary: #765657; + --md-sys-color-on-secondary: #ffffff; + --md-sys-color-secondary-container: #ffdada; + --md-sys-color-on-secondary-container: #2c1516; + --md-sys-color-tertiary: #76592f; + --md-sys-color-on-tertiary: #ffffff; + --md-sys-color-tertiary-container: #ffddb2; + --md-sys-color-on-tertiary-container: #291800; + --md-sys-color-error: #ba1a1a; + --md-sys-color-on-error: #ffffff; + --md-sys-color-error-container: #ffdad6; + --md-sys-color-on-error-container: #410002; + --md-sys-color-background: #fffbff; + --md-sys-color-on-background: #201a1a; + --md-sys-color-surface: #fffbff; + --md-sys-color-on-surface: #201a1a; + --md-sys-color-surface-variant: #f4dddd; + --md-sys-color-on-surface-variant: #524343; + --md-sys-color-outline: #857373; + --md-sys-color-outline-variant: #d7c1c1; + --md-sys-color-shadow: #000000; + --md-sys-color-scrim: #000000; + --md-sys-color-inverse-surface: #362f2f; + --md-sys-color-inverse-on-surface: #fbeeed; + --md-sys-color-inverse-primary: #ffb3b6; + --md-sys-color-surface-dim: #e4d7d7; + --md-sys-color-surface-bright: #fff8f7; + --md-sys-color-surface-container-lowest: #ffffff; + --md-sys-color-surface-container-low: #fef1f0; + --md-sys-color-surface-container: #f8ebea; + --md-sys-color-surface-container-high: #f2e5e5; + --md-sys-color-surface-container-highest: #ece0df; + } + + + + + +
+
+ +
+ + +
+
+
+
+
+

animautomata

+
+ +

+ Animautomata + +

+ + +

+ An open-source, zero-dependency, fully-typed solution for creating + high-quality, lightweight loading animations that fit your brand + identity, using the Canvas API. +

+ + +
    +
  • + Fully-typed (source written in Typescript). +
  • +
  • Zero-dependency.
  • +
  • + Add, transform, and remove loading animations with + one line of javascript. +
  • +
  • Simple but deeply configurable API.
  • +
  • + Create and experiment using the + Animautomata Forge web GUI +
  • +
  • + Plug-and-play React components are available with + animautomata-react. +
  • +
  • + No image files => faster loading. The minified + library size is ~30kb uncompressed (~6kb gzipped). For comparison + the first google image result for "loading animation + gif" + is over 80kb. +
  • +
  • + Use the abstract Animautomata parent class to + create your own custom presets. +
  • +
+ + +

+ Animautomata Forge +

+ + +

+ https://era-epoch.github.io/animautomata/docs/ +

+ + +

+ https://era-epoch.github.io/animautomata/examples/ +

+

with source code:

+

+ https://github.com/era-epoch/animautomata/blob/main/examples/examples.ts +

+ + +

via npm

+

npm install --save animautomata

+

via unpkg cdn

+

+ <script + src="https://unpkg.com/animautomata@latest/dist/min.js></script> +

+

via jsdeliver cdn

+

+ <script + src="https://cdn.jsdelivr.net/npm/animautomata@latest/dist/min.js"></script> +

+

via git

+

+ git clone https://github.com/era-epoch/animautomata.git +

+ + +

+ This project was created using + typescript, distributed via + npm, developed with + vite, tested with + jest, and has documentation created with + typedoc. +

+ + +

+ MIT +

+
+
+
+ + +
+
+
+

+ Generated using + TypeDoc +

+
+
+ + +