poline
Version:
color palette generator mico-lib
2 lines (1 loc) • 9.28 kB
JavaScript
var m=(i,t)=>{let[o,n,e]=i,c=.5,h=.5,r=Math.atan2(n-h,o-c)*(180/Math.PI);r=(360+r)%360;let a=e,l=Math.sqrt(Math.pow(n-h,2)+Math.pow(o-c,2))/c;return[r,a,t?1-l:l]},f=(i,t)=>{let[o,n,e]=i,c=.5,h=.5,s=o/(180/Math.PI),r=(t?1-e:e)*c,a=c+r*Math.cos(s),p=h+r*Math.sin(s);return[a,p,n]},F=(i=Math.random()*360,t=[Math.random(),Math.random()],o=[.75+Math.random()*.2,.3+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]]],I=(i=Math.random()*360,t=[Math.random(),Math.random(),Math.random()],o=[.75+Math.random()*.2,Math.random()*.2,.75+Math.random()*.2])=>[[i,t[0],o[0]],[(i+60+Math.random()*180)%360,t[1],o[1]],[(i+60+Math.random()*180)%360,t[2],o[2]]],v=(i,t,o,n=!1,e=(s,r)=>r?1-s:s,c=(s,r)=>r?1-s:s,h=(s,r)=>r?1-s:s)=>{let s=e(i,n),r=c(i,n),a=h(i,n),p=(1-s)*t[0]+s*o[0],l=(1-r)*t[1]+r*o[1],b=(1-a)*t[2]+a*o[2];return[p,l,b]},M=(i,t,o=4,n=!1,e=(s,r)=>r?1-s:s,c=(s,r)=>r?1-s:s,h=(s,r)=>r?1-s:s)=>{let s=[];for(let r=0;r<o;r++){let[a,p,l]=v(r/(o-1),i,t,n,e,c,h);s.push([a,p,l])}return s},x=i=>i,L=(i,t=!1)=>t?1-(1-i)**2:i**2,V=(i,t=!1)=>t?1-(1-i)**3:i**3,A=(i,t=!1)=>t?1-(1-i)**4:i**4,w=(i,t=!1)=>t?1-(1-i)**5:i**5,u=(i,t=!1)=>t?1-Math.sin((1-i)*Math.PI/2):Math.sin(i*Math.PI/2),y=(i,t=!1)=>t?1-Math.asin(1-i)/(Math.PI/2):Math.asin(i)/(Math.PI/2),S=(i,t=!1)=>t?1-Math.sqrt(1-i**2):1-Math.sqrt(1-i),E=i=>i**2*(3-2*i),X={linearPosition:x,exponentialPosition:L,quadraticPosition:V,cubicPosition:A,quarticPosition:w,sinusoidalPosition:u,asinusoidalPosition:y,arcPosition:S,smoothStepPosition:E},_=(i,t,o=!1)=>{let n=i[0],e=t[0],c=0;o&&n!==null&&e!==null?(c=Math.min(Math.abs(n-e),360-Math.abs(n-e)),c=c/360):c=n===null||e===null?0:n-e;let h=c,s=i[1]===null||t[1]===null?0:t[1]-i[1],r=i[2]===null||t[2]===null?0:t[2]-i[2];return Math.sqrt(h*h+s*s+r*r)},d=class{constructor({xyz:t,color:o,invertedLightness:n=!1}={}){this.x=0;this.y=0;this.z=0;this.color=[0,0,0];this._invertedLightness=!1;this._invertedLightness=n,this.positionOrColor({xyz:t,color:o,invertedLightness:n})}positionOrColor({xyz:t,color:o,invertedLightness:n=!1}){if(this._invertedLightness=n,t&&o||!t&&!o)throw new Error("Point must be initialized with either x,y,z or hsl");t?(this.x=t[0],this.y=t[1],this.z=t[2],this.color=m([this.x,this.y,this.z],n)):o&&(this.color=o,[this.x,this.y,this.z]=f(o,n))}set position([t,o,n]){this.x=t,this.y=o,this.z=n,this.color=m([this.x,this.y,this.z],this._invertedLightness)}get position(){return[this.x,this.y,this.z]}set hsl([t,o,n]){this.color=[t,o,n],[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}get hsl(){return this.color}get hslCSS(){let[t,o,n]=this.color;return`hsl(${t.toFixed(2)}, ${(o*100).toFixed(2)}%, ${(n*100).toFixed(2)}%)`}get oklchCSS(){let[t,o,n]=this.color;return`oklch(${(n*100).toFixed(2)}% ${(o*.4).toFixed(3)} ${t.toFixed(2)})`}get lchCSS(){let[t,o,n]=this.color;return`lch(${(n*100).toFixed(2)}% ${(o*150).toFixed(2)} ${t.toFixed(2)})`}set invertedLightness(t){this._invertedLightness=t,this.color=m([this.x,this.y,this.z],this._invertedLightness)}get invertedLightness(){return this._invertedLightness}shiftHue(t){this.color[0]=(360+(this.color[0]+t))%360,[this.x,this.y,this.z]=f(this.color,this._invertedLightness)}},g=class{constructor({anchorColors:t=F(),numPoints:o=4,positionFunction:n=u,positionFunctionX:e,positionFunctionY:c,positionFunctionZ:h,closedLoop:s,invertedLightness:r}={anchorColors:F(),numPoints:4,positionFunction:u,closedLoop:!1}){this._positionFunctionX=u;this._positionFunctionY=u;this._positionFunctionZ=u;this.connectLastAndFirstAnchor=!1;this._animationFrame=null;this._invertedLightness=!1;if(!t||t.length<2)throw new Error("Must have at least two anchor colors");this._anchorPoints=t.map(a=>new d({color:a,invertedLightness:r})),this._numPoints=o+2,this._positionFunctionX=e||n||u,this._positionFunctionY=c||n||u,this._positionFunctionZ=h||n||u,this.connectLastAndFirstAnchor=s||!1,this._invertedLightness=r||!1,this.updateAnchorPairs()}get numPoints(){return this._numPoints-2}set numPoints(t){if(t<1)throw new Error("Must have at least one point");this._numPoints=t+2,this.updateAnchorPairs()}set positionFunction(t){if(Array.isArray(t)){if(t.length!==3)throw new Error("Position function array must have 3 elements");if(typeof t[0]!="function"||typeof t[1]!="function"||typeof t[2]!="function")throw new Error("Position function array must have 3 functions");this._positionFunctionX=t[0],this._positionFunctionY=t[1],this._positionFunctionZ=t[2]}else this._positionFunctionX=t,this._positionFunctionY=t,this._positionFunctionZ=t;this.updateAnchorPairs()}get positionFunction(){return this._positionFunctionX===this._positionFunctionY&&this._positionFunctionX===this._positionFunctionZ?this._positionFunctionX:[this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ]}set positionFunctionX(t){this._positionFunctionX=t,this.updateAnchorPairs()}get positionFunctionX(){return this._positionFunctionX}set positionFunctionY(t){this._positionFunctionY=t,this.updateAnchorPairs()}get positionFunctionY(){return this._positionFunctionY}set positionFunctionZ(t){this._positionFunctionZ=t,this.updateAnchorPairs()}get positionFunctionZ(){return this._positionFunctionZ}get anchorPoints(){return this._anchorPoints}set anchorPoints(t){this._anchorPoints=t,this.updateAnchorPairs()}updateAnchorPairs(){this._anchorPairs=[];let t=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1;for(let o=0;o<t;o++){let n=[this.anchorPoints[o],this.anchorPoints[(o+1)%this.anchorPoints.length]];this._anchorPairs.push(n)}this.points=this._anchorPairs.map((o,n)=>{let e=o[0]?o[0].position:[0,0,0],c=o[1]?o[1].position:[0,0,0],h=this.shouldInvertEaseForSegment(n);return M(e,c,this._numPoints,!!h,this.positionFunctionX,this.positionFunctionY,this.positionFunctionZ).map(s=>new d({xyz:s,invertedLightness:this._invertedLightness}))})}addAnchorPoint({xyz:t,color:o,insertAtIndex:n}){let e=new d({xyz:t,color:o,invertedLightness:this._invertedLightness});return n!==void 0?this.anchorPoints.splice(n,0,e):this.anchorPoints.push(e),this.updateAnchorPairs(),e}removeAnchorPoint({point:t,index:o}){if(!t&&o===void 0)throw new Error("Must provide a point or index");if(this.anchorPoints.length<3)throw new Error("Must have at least two anchor points");let n;if(o!==void 0?n=o:t&&(n=this.anchorPoints.indexOf(t)),n>-1&&n<this.anchorPoints.length)this.anchorPoints.splice(n,1),this.updateAnchorPairs();else throw new Error("Point not found")}updateAnchorPoint({point:t,pointIndex:o,xyz:n,color:e}){if(o!==void 0&&(t=this.anchorPoints[o]),!t)throw new Error("Must provide a point or pointIndex");if(!n&&!e)throw new Error("Must provide a new xyz position or color");return n&&(t.position=n),e&&(t.hsl=e),this.updateAnchorPairs(),t}getClosestAnchorPoint({xyz:t,hsl:o,maxDistance:n=1}){if(!t&&!o)throw new Error("Must provide a xyz or hsl");let e;t?e=this.anchorPoints.map(s=>_(s.position,t)):o&&(e=this.anchorPoints.map(s=>_(s.hsl,o,!0)));let c=Math.min(...e);if(c>n)return null;let h=e.indexOf(c);return this.anchorPoints[h]||null}set closedLoop(t){this.connectLastAndFirstAnchor=t,this.updateAnchorPairs()}get closedLoop(){return this.connectLastAndFirstAnchor}set invertedLightness(t){this._invertedLightness=t,this.anchorPoints.forEach(o=>o.invertedLightness=t),this.updateAnchorPairs()}get invertedLightness(){return this._invertedLightness}get flattenedPoints(){return this.points.flat().filter((t,o)=>o!=0?o%this._numPoints:!0)}get colors(){let t=this.flattenedPoints.map(o=>o.color);return this.connectLastAndFirstAnchor&&this._anchorPoints.length!==2&&t.pop(),t}cssColors(t="hsl"){let o={hsl:e=>e.hslCSS,oklch:e=>e.oklchCSS,lch:e=>e.lchCSS},n=this.flattenedPoints.map(o[t]);return this.connectLastAndFirstAnchor&&n.pop(),n}get colorsCSS(){return this.cssColors("hsl")}get colorsCSSlch(){return this.cssColors("lch")}get colorsCSSoklch(){return this.cssColors("oklch")}shiftHue(t=20){this.anchorPoints.forEach(o=>o.shiftHue(t)),this.updateAnchorPairs()}getColorAt(t){if(t<0||t>1)throw new Error("Position must be between 0 and 1");if(this.anchorPoints.length===0)throw new Error("No anchor points available");let o=this.connectLastAndFirstAnchor?this.anchorPoints.length:this.anchorPoints.length-1,n=this.connectLastAndFirstAnchor&&this.anchorPoints.length===2?2:o,e=t*n,c=Math.floor(e),h=e-c,s=c>=n?n-1:c,r=c>=n?1:h,a=this._anchorPairs[s];if(!a||a.length<2||!a[0]||!a[1])return new d({color:this.anchorPoints[0]?.color||[0,0,0],invertedLightness:this._invertedLightness});let p=a[0].position,l=a[1].position,b=this.shouldInvertEaseForSegment(s),C=v(r,p,l,b,this._positionFunctionX,this._positionFunctionY,this._positionFunctionZ);return new d({xyz:C,invertedLightness:this._invertedLightness})}shouldInvertEaseForSegment(t){return!!(t%2||this.connectLastAndFirstAnchor&&this.anchorPoints.length===2&&t===0)}},{p5:P}=globalThis;if(P&&P.VERSION&&P.VERSION.startsWith("1.")){console.info("p5 < 1.x detected, adding poline to p5 prototype");let i=new g;P.prototype.poline=i;let t=()=>i.colors.map(o=>`hsl(${Math.round(o[0])},${o[1]*100}%,${o[2]*100}%)`);P.prototype.registerMethod("polineColors",t),globalThis.poline=i,globalThis.polineColors=t}export{d as ColorPoint,g as Poline,f as hslToPoint,m as pointToHSL,X as positionFunctions,F as randomHSLPair,I as randomHSLTriple};