Created
September 21, 2021 11:56
-
-
Save steveruizok/39b5c0831a68105ef66eeae47dfc3a37 to your computer and use it in GitHub Desktop.
Perfect freehand in Baku's pen tool.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
{ | |
"id": "bga2899d28", | |
"label": "Perfect", | |
"icon": "✍︎", | |
"parameters": [ | |
{ | |
"name": "size", | |
"type": "float", | |
"default": "16" | |
}, | |
{ | |
"name": "thinning", | |
"type": "float", | |
"default": ".5" | |
}, | |
{ | |
"name": "streamline", | |
"type": "float", | |
"default": ".5" | |
}, | |
{ | |
"name": "smoothing", | |
"type": "float", | |
"default": ".5" | |
}, | |
{ | |
"name": "strokeColor", | |
"type": "color", | |
"default": "#282a2e" | |
}, | |
{ | |
"name": "smoothing", | |
"type": "float", | |
"default": ".5" | |
}, | |
{ | |
"name": "strokeWidth", | |
"type": "float", | |
"default": 2 | |
}, | |
{ | |
"name": "strokeColor", | |
"type": "color", | |
"default": "#282a2e" | |
}, | |
{ | |
"name": "fillColor", | |
"type": "color", | |
"default": "#282a2e" | |
} | |
] | |
} | |
*/ | |
function Y(e,t,u,S=g=>g){return e*S(.5-t*(.5-u))}function p(e,t){return[e[0]+t[0],e[1]+t[1]]}function m(e,t){return[e[0]-t[0],e[1]-t[1]]}function f(e,t){return[e[0]*t,e[1]*t]}function fe(e,t){return[e[0]/t,e[1]/t]}function I(e){return[e[1],-e[0]]}function re(e,t){return e[0]*t[0]+e[1]*t[1]}function oe(e,t){return e[0]===t[0]&&e[1]===t[1]}function be(e){return Math.hypot(e[0],e[1])}function ge(e){return e[0]*e[0]+e[1]*e[1]}function Z(e,t){return ge(m(e,t))}function K(e){return fe(e,be(e))}function se(e,t){return Math.hypot(e[1]-t[1],e[0]-t[0])}function ue(e,t){return f(p(e,t),.5)}function V(e,t,u){let S=Math.sin(u),g=Math.cos(u),y=e[0]-t[0],o=e[1]-t[1],x=y*g-o*S,L=y*S+o*g;return[x+t[0],L+t[1]]}function N(e,t,u){return p(e,f(m(t,e),u))}function $(e,t,u){return p(e,f(t,u))}var{min:_,PI:de}=Math,ie=.275,j=de+1e-4;function pe(e,t={}){let{size:u=16,smoothing:S=.5,thinning:g=.5,simulatePressure:y=!0,easing:o=n=>n,start:x={},end:L={},last:q=!1}=t,{cap:k=!0,taper:P=0,easing:C=n=>n*(2-n)}=x,{cap:b=!0,taper:a=0,easing:T=n=>--n*n*n+1}=L;if(e.length===0||u<=0)return[];let U=e[e.length-1].runningLength,B=Math.pow(u*S,2),O=[],v=[],X=e.slice(0,10).reduce((n,i)=>{let r=i.pressure;if(y){let s=_(1,i.distance/u),l=_(1,1-s);r=_(1,n+(l-n)*(s*ie))}return(n+r)/2},e[0].pressure),c=Y(u,g,e[e.length-1].pressure,o),J,A=e[0].vector,z=e[0].point,F=z,E=z,M=F;for(let n=0;n<e.length-1;n++){let{pressure:i}=e[n],{point:r,vector:s,distance:l,runningLength:R}=e[n];if(U-R<3)continue;if(g){if(y){let D=_(1,l/u),W=_(1,1-D);i=_(1,X+(W-X)*(D*ie))}c=Y(u,g,i,o)}else c=u/2;J===void 0&&(J=c);let ae=R<P?C(R/P):1,le=U-R<a?T((U-R)/a):1;c=Math.max(.01,c*Math.min(ae,le));let ee=e[n+1].vector,te=re(s,ee);if(te<0){let D=f(I(A),c);for(let W=1/13,H=0;H<=1;H+=W)E=V(m(r,D),r,j*H),O.push(E),M=V(p(r,D),r,j*-H),v.push(M);z=E,F=M;continue}let ne=f(I(N(ee,s,te)),c);E=m(r,ne),(n===0||Z(z,E)>B)&&(O.push(E),z=E),M=p(r,ne),(n===0||Z(F,M)>B)&&(v.push(M),F=M),X=i,A=s}let d=e[0].point.slice(0,2),h=e.length>1?e[e.length-1].point.slice(0,2):p(e[0].point,[1,1]),Q=O.length<=1||v.length<=1,w=[],G=[];if(Q){if(!(P||a)||q){let n=$(d,K(I(m(d,h))),-(J||c)),i=[];for(let r=1/13,s=r;s<=1;s+=r)i.push(V(n,d,j*2*s));return i}}else{if(P||a&&Q)w.push(d,p(d,[.1,0]));else if(k)for(let r=1/13,s=r;s<=1;s+=r){let l=V(v[0],d,j*s);w.push(l)}else{let r=m(O[0],v[0]),s=f(r,.5),l=f(r,.51);w.push(m(d,s),m(d,l),p(d,l),p(d,s))}let n=ue(O[O.length-1],v[v.length-1]),i=I(K(m(h,n)));if(a||P&&Q)G.push(h,p(h,[1,0]));else if(b){let r=$(h,i,c);for(let s=1/29,l=0;l<=1;l+=s){let R=V(r,h,j*3*l);G.push(R)}}else G.push(p(h,f(i,c)),p(h,f(i,c*.99)),m(h,f(i,c*.99)),m(h,f(i,c)))}return O.concat(G,v.reverse(),w)}function me(e,t={}){var C;let{streamline:u=.5,size:S=16,last:g=!1}=t;if(e.length===0)return[];let y=.15+(1-u)*.85,o=Array.isArray(e[0])?e:e.map(({x:b,y:a,pressure:T=.5})=>[b,a,T]);o.length===1&&(o=[...o,[...p(o[0],[1,1]),...o[0].slice(2)]]);let x=[{point:[o[0][0],o[0][1]],pressure:o[0][2]||.25,vector:[1,1],distance:0,runningLength:0}],L=!1,q=0,k=x[0],P=o.length-1;for(let b=1;b<o.length;b++){let a=g&&b===P?o[b]:N(k.point,o[b],y);if(oe(k.point,a))continue;let T=se(a,k.point);if(q+=T,b<P&&!L){if(q<S)continue;L=!0}k={point:a,pressure:o[b][2]||.5,vector:K(m(k.point,a)),distance:T,runningLength:q},x.push(k)}return x[0].vector=((C=x[1])==null?void 0:C.vector)||[0,0],x}function ce(e,t={}){return pe(me(e,t),t)}var qe=ce; | |
function getSvgPathFromStroke(stroke) { | |
if (!stroke.length) return '' | |
const d = stroke.reduce( | |
(acc, [x0, y0], i, arr) => { | |
const [x1, y1] = arr[(i + 1) % arr.length] | |
acc.push(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2) | |
return acc | |
}, | |
['M', ...stroke[0], 'Q'] | |
) | |
d.push('Z') | |
return d.join(' ') | |
} | |
let stroke, path, points = [] | |
const getStroke = ce | |
function begin() { | |
} | |
function press() { | |
points = [] | |
points.push([mouse.x, mouse.y]) | |
path=new Path() | |
path.strokeColor = strokeColor | |
path.fillColor = fillColor | |
path.strokeWidth = strokeWidth | |
} | |
function drag() { | |
points.push([mouse.x, mouse.y]) | |
stroke = getStroke(points, { | |
size, | |
thinning, | |
streamline, | |
smoothing, | |
}) | |
pathData = getSvgPathFromStroke(stroke) | |
// Remove the old path | |
path?.remove() | |
// Create a new path | |
path=new Path(pathData) | |
path.strokeColor = strokeColor | |
path.fillColor = fillColor | |
path.strokeWidth = strokeWidth | |
} | |
function release() { | |
} | |
function move() { | |
} | |
function end() { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment