@leafer-in/corner 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/corner.cjs +264 -0
- package/dist/corner.esm.js +262 -0
- package/dist/corner.esm.min.js +2 -0
- package/dist/corner.esm.min.js.map +1 -0
- package/dist/corner.js +253 -0
- package/dist/corner.min.cjs +2 -0
- package/dist/corner.min.cjs.map +1 -0
- package/dist/corner.min.js +2 -0
- package/dist/corner.min.js.map +1 -0
- package/package.json +41 -0
- package/src/PathCorner.ts +200 -0
- package/src/helper.ts +95 -0
- package/src/index.ts +5 -0
- package/types/index.d.ts +2 -0
package/dist/corner.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
(function(draw) {
|
|
2
|
+
"use strict";
|
|
3
|
+
function getTangentDistance(r, x, y, lastX, lastY, nextX, nextY) {
|
|
4
|
+
const ux = lastX - x, uy = lastY - y;
|
|
5
|
+
const vx = nextX - x, vy = nextY - y;
|
|
6
|
+
const lenU = Math.sqrt(ux * ux + uy * uy);
|
|
7
|
+
const lenV = Math.sqrt(vx * vx + vy * vy);
|
|
8
|
+
if (lenU < .001 || lenV < .001) return 0;
|
|
9
|
+
const cosTheta = (ux * vx + uy * vy) / (lenU * lenV);
|
|
10
|
+
const safeCos = Math.max(-.99999, Math.min(.99999, cosTheta));
|
|
11
|
+
let d = r * Math.sqrt((1 - safeCos) / (1 + safeCos));
|
|
12
|
+
const maxD = Math.min(lenU / 2, lenV / 2);
|
|
13
|
+
return Math.min(d, maxD);
|
|
14
|
+
}
|
|
15
|
+
function getCorrectT(d, x, y, x1, y1, x2, y2, toX, toY) {
|
|
16
|
+
if (d <= 0) return 0;
|
|
17
|
+
const chordLen = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2));
|
|
18
|
+
if (d >= chordLen) return .5;
|
|
19
|
+
const vx0 = 3 * (x1 - x);
|
|
20
|
+
const vy0 = 3 * (y1 - y);
|
|
21
|
+
let v0mag = Math.sqrt(vx0 * vx0 + vy0 * vy0);
|
|
22
|
+
if (v0mag < 1e-6) v0mag = chordLen || 1;
|
|
23
|
+
let t = Math.min(.5, d / v0mag);
|
|
24
|
+
const tempP = {
|
|
25
|
+
x: 0,
|
|
26
|
+
y: 0
|
|
27
|
+
};
|
|
28
|
+
for (let i = 0; i < 5; i++) {
|
|
29
|
+
draw.BezierHelper.getPointAndSet(t, x, y, x1, y1, x2, y2, toX, toY, tempP);
|
|
30
|
+
const dx = tempP.x - x;
|
|
31
|
+
const dy = tempP.y - y;
|
|
32
|
+
const currentDist = Math.sqrt(dx * dx + dy * dy);
|
|
33
|
+
if (currentDist < 1e-6) {
|
|
34
|
+
t = t * 1.5;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const vxt = draw.BezierHelper.getDerivative(t, x, x1, x2, toX);
|
|
38
|
+
const vyt = draw.BezierHelper.getDerivative(t, y, y1, y2, toY);
|
|
39
|
+
const f_prime = (dx * vxt + dy * vyt) / currentDist;
|
|
40
|
+
if (Math.abs(f_prime) < 1e-6) break;
|
|
41
|
+
const deltaT = (currentDist - d) / f_prime;
|
|
42
|
+
const nextT = t - deltaT;
|
|
43
|
+
const safeNextT = Math.max(0, Math.min(.6, nextT));
|
|
44
|
+
if (Math.abs(safeNextT - t) < 1e-5) {
|
|
45
|
+
t = safeNextT;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
t = safeNextT;
|
|
49
|
+
}
|
|
50
|
+
return Math.max(0, Math.min(.5, t));
|
|
51
|
+
}
|
|
52
|
+
const {M: M, L: L, C: C, Z: Z} = draw.PathCommandMap;
|
|
53
|
+
const {getCenterX: getCenterX, getCenterY: getCenterY} = draw.PointHelper;
|
|
54
|
+
const {arcTo: arcTo} = draw.PathCommandDataHelper;
|
|
55
|
+
draw.PathCorner.smooth = function smooth(data, cornerRadius, _cornerSmoothing) {
|
|
56
|
+
const radius = data.radius;
|
|
57
|
+
if (isNeedConvert(data)) data = draw.PathConvert.toCanvasData(data, true);
|
|
58
|
+
let command, lastCommand, commandLen;
|
|
59
|
+
let i = 0, countCommand = 0, x = 0, y = 0, startX = 0, startY = 0, startR = 0, secondX = 0, secondY = 0, lastX = 0, lastY = 0, r, x1, y1, x2, y2, toX, toY;
|
|
60
|
+
if (draw.isArray(cornerRadius)) cornerRadius = cornerRadius[0] || 0;
|
|
61
|
+
const len = data.length, three = len === 9;
|
|
62
|
+
const smooth = [];
|
|
63
|
+
while (i < len) {
|
|
64
|
+
command = data[i];
|
|
65
|
+
r = radius ? draw.isUndefined(radius[countCommand]) ? cornerRadius : radius[countCommand] : cornerRadius;
|
|
66
|
+
switch (command) {
|
|
67
|
+
case M:
|
|
68
|
+
startX = lastX = data[i + 1];
|
|
69
|
+
startY = lastY = data[i + 2];
|
|
70
|
+
startR = r;
|
|
71
|
+
i += 3;
|
|
72
|
+
const end = findEndPoint(data, i);
|
|
73
|
+
switch (data[i]) {
|
|
74
|
+
case L:
|
|
75
|
+
secondX = data[i + 1];
|
|
76
|
+
secondY = data[i + 2];
|
|
77
|
+
if (three) smooth.push(M, startX, startY); else {
|
|
78
|
+
if (end) smooth.push(M, getCenterX(startX, secondX), getCenterY(startY, secondY)); else smooth.push(M, startX, startY);
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
|
|
82
|
+
case C:
|
|
83
|
+
if (end) {
|
|
84
|
+
const {left: left, right: right} = setAfterC(data, i, r, end.x, end.y, startX, startY, data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6]);
|
|
85
|
+
if (left && right) {
|
|
86
|
+
smooth.push(M, secondX = left[4], secondY = left[5]);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
default:
|
|
92
|
+
smooth.push(M, secondX = startX, secondY = startY);
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
|
|
96
|
+
case L:
|
|
97
|
+
x = data[i + 1];
|
|
98
|
+
y = data[i + 2];
|
|
99
|
+
i += 3;
|
|
100
|
+
switch (data[i]) {
|
|
101
|
+
case L:
|
|
102
|
+
arcTo(smooth, x, y, data[i + 1], data[i + 2], r, lastX, lastY, three);
|
|
103
|
+
break;
|
|
104
|
+
|
|
105
|
+
case C:
|
|
106
|
+
const {left: left, right: right} = setAfterC(data, i, r, lastX, lastY, x, y, data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6]);
|
|
107
|
+
if (left && right) arcTo(smooth, x, y, left[4], left[5], r, lastX, lastY, three); else smooth.push(L, x, y);
|
|
108
|
+
break;
|
|
109
|
+
|
|
110
|
+
case Z:
|
|
111
|
+
arcTo(smooth, x, y, startX, startY, r, lastX, lastY, three);
|
|
112
|
+
break;
|
|
113
|
+
|
|
114
|
+
default:
|
|
115
|
+
smooth.push(L, x, y);
|
|
116
|
+
}
|
|
117
|
+
lastX = x;
|
|
118
|
+
lastY = y;
|
|
119
|
+
break;
|
|
120
|
+
|
|
121
|
+
case C:
|
|
122
|
+
x1 = data[i + 1];
|
|
123
|
+
y1 = data[i + 2];
|
|
124
|
+
x2 = data[i + 3];
|
|
125
|
+
y2 = data[i + 4];
|
|
126
|
+
x = data[i + 5];
|
|
127
|
+
y = data[i + 6];
|
|
128
|
+
i += 7;
|
|
129
|
+
switch (data[i]) {
|
|
130
|
+
case L:
|
|
131
|
+
toX = data[i + 1], toY = data[i + 2];
|
|
132
|
+
setBeforeC(smooth, r, lastX, lastY, x1, y1, x2, y2, x, y, toX, toY, three);
|
|
133
|
+
break;
|
|
134
|
+
|
|
135
|
+
case C:
|
|
136
|
+
smooth.push(C, x1, y1, x2, y2, x, y);
|
|
137
|
+
break;
|
|
138
|
+
|
|
139
|
+
case Z:
|
|
140
|
+
toX = startX, toY = startY;
|
|
141
|
+
setBeforeC(smooth, r, lastX, lastY, x1, y1, x2, y2, x, y, toX, toY, three);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
lastX = x;
|
|
145
|
+
lastY = y;
|
|
146
|
+
break;
|
|
147
|
+
|
|
148
|
+
case Z:
|
|
149
|
+
if (lastCommand !== Z) {
|
|
150
|
+
arcTo(smooth, startX, startY, secondX, secondY, startR, lastX, lastY, three);
|
|
151
|
+
smooth.push(Z);
|
|
152
|
+
}
|
|
153
|
+
i += 1;
|
|
154
|
+
break;
|
|
155
|
+
|
|
156
|
+
default:
|
|
157
|
+
commandLen = draw.PathNumberCommandLengthMap[command];
|
|
158
|
+
for (let j = 0; j < commandLen; j++) smooth.push(data[i + j]);
|
|
159
|
+
i += commandLen;
|
|
160
|
+
}
|
|
161
|
+
lastCommand = command;
|
|
162
|
+
countCommand++;
|
|
163
|
+
}
|
|
164
|
+
return smooth;
|
|
165
|
+
};
|
|
166
|
+
function isNeedConvert(data) {
|
|
167
|
+
let command, i = 0;
|
|
168
|
+
const len = data.length;
|
|
169
|
+
while (i < len) {
|
|
170
|
+
command = data[i];
|
|
171
|
+
switch (command) {
|
|
172
|
+
case M:
|
|
173
|
+
i += 3;
|
|
174
|
+
break;
|
|
175
|
+
|
|
176
|
+
case L:
|
|
177
|
+
i += 3;
|
|
178
|
+
break;
|
|
179
|
+
|
|
180
|
+
case C:
|
|
181
|
+
i += 7;
|
|
182
|
+
break;
|
|
183
|
+
|
|
184
|
+
case Z:
|
|
185
|
+
i += 1;
|
|
186
|
+
break;
|
|
187
|
+
|
|
188
|
+
default:
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
function findEndPoint(data, i) {
|
|
195
|
+
let command, commandLen, x, y;
|
|
196
|
+
const len = data.length;
|
|
197
|
+
while (i < len) {
|
|
198
|
+
command = data[i];
|
|
199
|
+
switch (command) {
|
|
200
|
+
case M:
|
|
201
|
+
return undefined;
|
|
202
|
+
|
|
203
|
+
case L:
|
|
204
|
+
x = data[i + 1];
|
|
205
|
+
y = data[i + 2];
|
|
206
|
+
i += 3;
|
|
207
|
+
break;
|
|
208
|
+
|
|
209
|
+
case C:
|
|
210
|
+
x = data[i + 5];
|
|
211
|
+
y = data[i + 6];
|
|
212
|
+
i += 7;
|
|
213
|
+
break;
|
|
214
|
+
|
|
215
|
+
case Z:
|
|
216
|
+
return {
|
|
217
|
+
x: x,
|
|
218
|
+
y: y
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
default:
|
|
222
|
+
commandLen = draw.PathNumberCommandLengthMap[command];
|
|
223
|
+
i += commandLen;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
function setAfterC(data, i, cornerRadius, lastX, lastY, fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
229
|
+
const d = getTangentDistance(cornerRadius, fromX, fromY, lastX, lastY, x1, y1);
|
|
230
|
+
const t = getCorrectT(d, fromX, fromY, x1, y1, x2, y2, toX, toY);
|
|
231
|
+
const two = draw.BezierHelper.cut(t, fromX, fromY, x1, y1, x2, y2, toX, toY);
|
|
232
|
+
const {left: left, right: right} = two;
|
|
233
|
+
if (left && right) {
|
|
234
|
+
data[i + 1] = right[0];
|
|
235
|
+
data[i + 2] = right[1];
|
|
236
|
+
data[i + 3] = right[2];
|
|
237
|
+
data[i + 4] = right[3];
|
|
238
|
+
}
|
|
239
|
+
return two;
|
|
240
|
+
}
|
|
241
|
+
function setBeforeC(smooth, cornerRadius, fromX, fromY, x1, y1, x2, y2, toX, toY, nextX, nextY, three) {
|
|
242
|
+
const d = getTangentDistance(cornerRadius, toX, toY, x2, y2, nextX, nextY);
|
|
243
|
+
const t = getCorrectT(d, toX, toY, x2, y2, x1, y1, fromX, fromY);
|
|
244
|
+
const {left: left, right: right} = draw.BezierHelper.cut(1 - t, fromX, fromY, x1, y1, x2, y2, toX, toY);
|
|
245
|
+
if (left && right) {
|
|
246
|
+
smooth.push(C, left[0], left[1], left[2], left[3], left[4], left[5]);
|
|
247
|
+
arcTo(smooth, toX, toY, nextX, nextY, cornerRadius, left[4], left[5], three);
|
|
248
|
+
} else {
|
|
249
|
+
smooth.push(C, x1, y1, x2, y2, toX, toY);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
draw.Plugin.add("corner");
|
|
253
|
+
})(LeaferUI);
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var e=require("@leafer-ui/draw");function t(e,t,a,r,n,s,c){const h=r-t,i=n-a,o=s-t,u=c-a,f=Math.sqrt(h*h+i*i),l=Math.sqrt(o*o+u*u);if(f<.001||l<.001)return 0;const p=(h*o+i*u)/(f*l),M=Math.max(-.99999,Math.min(.99999,p));let b=e*Math.sqrt((1-M)/(1+M));const m=Math.min(f/2,l/2);return Math.min(b,m)}function a(t,a,r,n,s,c,h,i,o){if(t<=0)return 0;const u=Math.sqrt(Math.pow(i-a,2)+Math.pow(o-r,2));if(t>=u)return.5;const f=3*(n-a),l=3*(s-r);let p=Math.sqrt(f*f+l*l);p<1e-6&&(p=u||1);let M=Math.min(.5,t/p);const b={x:0,y:0};for(let u=0;u<5;u++){e.BezierHelper.getPointAndSet(M,a,r,n,s,c,h,i,o,b);const u=b.x-a,f=b.y-r,l=Math.sqrt(u*u+f*f);if(l<1e-6){M*=1.5;continue}const p=(u*e.BezierHelper.getDerivative(M,a,n,c,i)+f*e.BezierHelper.getDerivative(M,r,s,h,o))/l;if(Math.abs(p)<1e-6)break;const m=M-(l-t)/p,k=Math.max(0,Math.min(.6,m));if(Math.abs(k-M)<1e-5){M=k;break}M=k}return Math.max(0,Math.min(.5,M))}const{M:r,L:n,C:s,Z:c}=e.PathCommandMap,{getCenterX:h,getCenterY:i}=e.PointHelper,{arcTo:o}=e.PathCommandDataHelper;function u(t,a){let h,i,o,u;const f=t.length;for(;a<f;)switch(h=t[a],h){case r:return;case n:o=t[a+1],u=t[a+2],a+=3;break;case s:o=t[a+5],u=t[a+6],a+=7;break;case c:return{x:o,y:u};default:i=e.PathNumberCommandLengthMap[h],a+=i}}function f(r,n,s,c,h,i,o,u,f,l,p,M,b){const m=a(t(s,i,o,c,h,u,f),i,o,u,f,l,p,M,b),k=e.BezierHelper.cut(m,i,o,u,f,l,p,M,b),{left:d,right:g}=k;return d&&g&&(r[n+1]=g[0],r[n+2]=g[1],r[n+3]=g[2],r[n+4]=g[3]),k}function l(r,n,c,h,i,u,f,l,p,M,b,m,k){const d=a(t(n,p,M,f,l,b,m),p,M,f,l,i,u,c,h),{left:g,right:C}=e.BezierHelper.cut(1-d,c,h,i,u,f,l,p,M);g&&C?(r.push(s,g[0],g[1],g[2],g[3],g[4],g[5]),o(r,p,M,b,m,n,g[4],g[5],k)):r.push(s,i,u,f,l,p,M)}e.PathCorner.smooth=function(t,a,p){const M=t.radius;let b,m,k;(function(e){let t,a=0;const h=e.length;for(;a<h;)switch(t=e[a],t){case r:case n:a+=3;break;case s:a+=7;break;case c:a+=1;break;default:return!0}return!1})(t)&&(t=e.PathConvert.toCanvasData(t,!0));let d,g,C,w,P,q,v,x=0,H=0,y=0,z=0,B=0,D=0,L=0,A=0,N=0,S=0,T=0;e.isArray(a)&&(a=a[0]||0);const U=t.length,X=9===U,Y=[];for(;x<U;){switch(b=t[x],d=M?e.isUndefined(M[H])?a:M[H]:a,b){case r:B=S=t[x+1],D=T=t[x+2],L=d,x+=3;const a=u(t,x);switch(t[x]){case n:A=t[x+1],N=t[x+2],X?Y.push(r,B,D):a?Y.push(r,h(B,A),i(D,N)):Y.push(r,B,D);break;case s:if(a){const{left:e,right:n}=f(t,x,d,a.x,a.y,B,D,t[x+1],t[x+2],t[x+3],t[x+4],t[x+5],t[x+6]);if(e&&n){Y.push(r,A=e[4],N=e[5]);break}}default:Y.push(r,A=B,N=D)}break;case n:switch(y=t[x+1],z=t[x+2],x+=3,t[x]){case n:o(Y,y,z,t[x+1],t[x+2],d,S,T,X);break;case s:const{left:e,right:a}=f(t,x,d,S,T,y,z,t[x+1],t[x+2],t[x+3],t[x+4],t[x+5],t[x+6]);e&&a?o(Y,y,z,e[4],e[5],d,S,T,X):Y.push(n,y,z);break;case c:o(Y,y,z,B,D,d,S,T,X);break;default:Y.push(n,y,z)}S=y,T=z;break;case s:switch(g=t[x+1],C=t[x+2],w=t[x+3],P=t[x+4],y=t[x+5],z=t[x+6],x+=7,t[x]){case n:q=t[x+1],v=t[x+2],l(Y,d,S,T,g,C,w,P,y,z,q,v,X);break;case s:Y.push(s,g,C,w,P,y,z);break;case c:q=B,v=D,l(Y,d,S,T,g,C,w,P,y,z,q,v,X)}S=y,T=z;break;case c:m!==c&&(o(Y,B,D,A,N,L,S,T,X),Y.push(c)),x+=1;break;default:k=e.PathNumberCommandLengthMap[b];for(let e=0;e<k;e++)Y.push(t[x+e]);x+=k}m=b,H++}return Y},e.Plugin.add("corner");
|
|
2
|
+
//# sourceMappingURL=corner.min.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corner.min.cjs","sources":["../../../../../../src/in/packages/corner/src/helper.ts","../../../../../../src/in/packages/corner/src/PathCorner.ts","../../../../../../src/in/packages/corner/src/index.ts"],"sourcesContent":["import { BezierHelper } from '@leafer-ui/draw'\n\n\n// 获取圆角切线距离\nexport function getTangentDistance(r: number, x: number, y: number, lastX: number, lastY: number, nextX: number, nextY: number): number {\n // 1. 构造入射向量 U (P -> lastP) 和出射向量 V (P -> nextP)\n const ux = lastX - x, uy = lastY - y\n const vx = nextX - x, vy = nextY - y\n\n // 2. 计算向量长度(平方和开方)\n const lenU = Math.sqrt(ux * ux + uy * uy)\n const lenV = Math.sqrt(vx * vx + vy * vy)\n\n // 3. 边界防御:若线段长度几乎为0,则不产生圆角\n if (lenU < 0.001 || lenV < 0.001) return 0\n\n // 4. 计算向量夹角余弦值 cos(θ) = (U·V) / (|U|*|V|)\n const cosTheta = (ux * vx + uy * vy) / (lenU * lenV)\n\n // 5. 精度钳位:防止浮点误差导致 cos 越界 [-1, 1],避开分母为0的情况\n const safeCos = Math.max(-0.99999, Math.min(0.99999, cosTheta))\n\n // 6. 核心几何推导:d = r * sqrt((1 - cosθ) / (1 + cosθ))\n let d = r * Math.sqrt((1 - safeCos) / (1 + safeCos))\n\n // 7. 【关键性能与安全约束】:最大距离不得超过相邻边长的一半\n // 这样可以确保相邻顶点的圆角不会发生几何重叠或路径自交。\n const maxD = Math.min(lenU / 2, lenV / 2)\n return Math.min(d, maxD)\n}\n\n// 精准定位贝塞尔曲线参数 t\nexport function getCorrectT(d: number, x: number, y: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number): number {\n if (d <= 0) return 0\n\n // 1. 预估总弦长(起点到终点的直线距离)\n const chordLen = Math.sqrt((toX - x) ** 2 + (toY - y) ** 2)\n\n // 2. 边界保护:若要求的距离超过弦长,为了路径安全,强制限制在曲线 50% 处\n if (d >= chordLen) return 0.5\n\n // 3. 初始猜测值估算:利用 t=0 处的瞬时速度矢量 v(0) = 3*(P1 - P0)\n const vx0 = 3 * (x1 - x)\n const vy0 = 3 * (y1 - y)\n let v0mag = Math.sqrt(vx0 * vx0 + vy0 * vy0)\n\n // 【优化点】:若起点与控制点重合(初速度为0),降级使用弦长线性比例,防止 NaN\n if (v0mag < 1e-6) v0mag = chordLen || 1\n\n let t = Math.min(0.5, d / v0mag)\n const tempP = { x: 0, y: 0 }\n\n // 4. 牛顿迭代 (Newton-Raphson) 循环\n for (let i = 0; i < 5; i++) {\n // 获取当前参数 t 对应的坐标点\n BezierHelper.getPointAndSet(t, x, y, x1, y1, x2, y2, toX, toY, tempP)\n\n const dx = tempP.x - x\n const dy = tempP.y - y\n const currentDist = Math.sqrt(dx * dx + dy * dy)\n\n // 数值稳定性检查:若当前点过于靠近起点,尝试向外探测\n if (currentDist < 1e-6) {\n t = t * 1.5\n continue\n }\n\n // 计算当前 t 处的导数向量 (x', y')\n const vxt = BezierHelper.getDerivative(t, x, x1, x2, toX)\n const vyt = BezierHelper.getDerivative(t, y, y1, y2, toY)\n\n // 计算目标函数的导数 f'(t) = (dx*x' + dy*y') / currentDist\n const f_prime = (dx * vxt + dy * vyt) / currentDist\n\n // 如果导数过小,说明进入平台期或计算异常,停止迭代\n if (Math.abs(f_prime) < 1e-6) break\n\n // 牛顿法公式:t_next = t - f(t) / f'(t)\n const deltaT = (currentDist - d) / f_prime\n const nextT = t - deltaT\n\n // 【收敛域保护】:强制限制在 [0, 0.6] 范围内寻找最优解,防止迭代跳出贝塞尔曲线有效区间\n const safeNextT = Math.max(0, Math.min(0.6, nextT))\n\n // 精度满足 1e-5 (像素级精度) 提前退出\n if (Math.abs(safeNextT - t) < 1e-5) {\n t = safeNextT\n break\n }\n t = safeNextT\n }\n\n // 最终返回结果,上限截断在 0.5 处,确保圆弧不会占据整条曲线导致形状崩坏\n return Math.max(0, Math.min(0.5, t))\n}","import { IPathCommandData, IPathCommandDataWithRadius, IPointData } from '@leafer-ui/interface'\nimport { PathCorner, PointHelper, PathCommandMap as Command, PathNumberCommandLengthMap, isArray, isUndefined, PathCommandDataHelper, BezierHelper, PathConvert } from '@leafer-ui/draw'\n\nimport { getCorrectT, getTangentDistance } from './helper'\n\n\nconst { M, L, C, Z } = Command\nconst { getCenterX, getCenterY } = PointHelper\nconst { arcTo } = PathCommandDataHelper\n\nPathCorner.smooth = function smooth(data: IPathCommandData, cornerRadius: number, _cornerSmoothing?: number): IPathCommandData {\n\n const radius = (data as any as IPathCommandDataWithRadius).radius // 独立圆角\n if (isNeedConvert(data)) data = PathConvert.toCanvasData(data, true)\n\n let command: number, lastCommand: number, commandLen\n let i = 0, countCommand = 0, x = 0, y = 0, startX = 0, startY = 0, startR = 0, secondX = 0, secondY = 0, lastX = 0, lastY = 0, r: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number\n if (isArray(cornerRadius)) cornerRadius = cornerRadius[0] || 0\n\n const len = data.length, three = len === 9 // 3个点时可以加大圆角\n const smooth: IPathCommandData = []\n\n while (i < len) {\n command = data[i]\n r = radius ? (isUndefined(radius[countCommand]) ? cornerRadius : radius[countCommand]) : cornerRadius\n switch (command) {\n case M: //moveto(x, y)\n startX = lastX = data[i + 1]\n startY = lastY = data[i + 2]\n startR = r\n i += 3\n const end = findEndPoint(data, i)\n switch (data[i]) { // next command\n case L: // lineTo()\n secondX = data[i + 1]\n secondY = data[i + 2]\n if (three) smooth.push(M, startX, startY)\n else {\n if (end) smooth.push(M, getCenterX(startX, secondX), getCenterY(startY, secondY))\n else smooth.push(M, startX, startY)\n }\n break\n case C: // bezierCurveTo()\n if (end) {\n const { left, right } = setAfterC(data, i, r, end.x, end.y, startX, startY, data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6])\n if (left && right) {\n smooth.push(M, secondX = left[4], secondY = left[5])\n break\n }\n }\n default:\n smooth.push(M, secondX = startX, secondY = startY)\n }\n break\n case L: //lineto(x, y)\n x = data[i + 1]\n y = data[i + 2]\n i += 3\n switch (data[i]) { // next command\n case L: // lineTo()\n arcTo(smooth, x, y, data[i + 1], data[i + 2], r, lastX, lastY, three) // use arcTo(x1, y1, x2, y2, radius)\n break\n case C: // bezierCurveTo()\n const { left, right } = setAfterC(data, i, r, lastX, lastY, x, y, data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6])\n if (left && right) arcTo(smooth, x, y, left[4], left[5], r, lastX, lastY, three)\n else smooth.push(L, x, y)\n break\n case Z: // closePath()\n arcTo(smooth, x, y, startX, startY, r, lastX, lastY, three) // use arcTo(x1, y1, x2, y2, radius)\n break\n default:\n smooth.push(L, x, y)\n }\n lastX = x\n lastY = y\n break\n case C:\n x1 = data[i + 1]\n y1 = data[i + 2]\n x2 = data[i + 3]\n y2 = data[i + 4]\n x = data[i + 5]\n y = data[i + 6]\n i += 7\n switch (data[i]) { // next command\n case L: // lineTo()\n toX = data[i + 1], toY = data[i + 2]\n setBeforeC(smooth, r, lastX, lastY, x1, y1, x2, y2, x, y, toX, toY, three)\n break\n case C: //\n smooth.push(C, x1, y1, x2, y2, x, y)\n break\n case Z: // closePath()\n toX = startX, toY = startY\n setBeforeC(smooth, r, lastX, lastY, x1, y1, x2, y2, x, y, toX, toY, three)\n break\n }\n lastX = x\n lastY = y\n break\n case Z: //closepath()\n if (lastCommand !== Z) { // fix: 重复的 Z 导致的问题\n arcTo(smooth, startX, startY, secondX, secondY, startR, lastX, lastY, three) // use arcTo(x1, y1, x2, y2, radius)\n smooth.push(Z)\n }\n i += 1\n break\n default:\n commandLen = PathNumberCommandLengthMap[command]\n for (let j = 0; j < commandLen; j++) smooth.push(data[i + j])\n i += commandLen\n }\n lastCommand = command\n countCommand++\n }\n\n return smooth\n}\n\n\nfunction isNeedConvert(data: IPathCommandData): boolean {\n let command: number, i = 0\n const len = data.length\n while (i < len) {\n command = data[i]\n switch (command) {\n case M: //moveto(x, y)\n i += 3\n break\n case L: //lineto(x, y)\n i += 3\n break\n case C: // bezierCurveTo()\n i += 7\n break\n case Z: //closepath()\n i += 1\n break\n default:\n return true\n }\n }\n return false\n}\n\nfunction findEndPoint(data: IPathCommandData, i: number): IPointData {\n let command: number, commandLen: number, x: number, y: number\n const len = data.length\n while (i < len) {\n command = data[i]\n switch (command) {\n case M: //moveto(x, y)\n return undefined\n case L: //lineto(x, y)\n x = data[i + 1]\n y = data[i + 2]\n i += 3\n break\n case C: // bezierCurveTo()\n x = data[i + 5]\n y = data[i + 6]\n i += 7\n break\n case Z: //closepath()\n return { x, y }\n default:\n commandLen = PathNumberCommandLengthMap[command]\n i += commandLen\n }\n }\n return undefined\n}\n\n\nfunction setAfterC(data: IPathCommandData, i: number, cornerRadius: number, lastX: number, lastY: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number) {\n const d = getTangentDistance(cornerRadius, fromX, fromY, lastX, lastY, x1, y1)\n const t = getCorrectT(d, fromX, fromY, x1, y1, x2, y2, toX, toY)\n const two = BezierHelper.cut(t, fromX, fromY, x1, y1, x2, y2, toX, toY)\n const { left, right } = two\n\n if (left && right) {\n data[i + 1] = right[0]; data[i + 2] = right[1]\n data[i + 3] = right[2]; data[i + 4] = right[3]\n }\n\n return two\n}\n\nfunction setBeforeC(smooth: IPathCommandData, cornerRadius: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number, nextX: number, nextY: number, three: boolean) {\n const d = getTangentDistance(cornerRadius, toX, toY, x2, y2, nextX, nextY) // 反向\n const t = getCorrectT(d, toX, toY, x2, y2, x1, y1, fromX, fromY) // 反向\n const { left, right } = BezierHelper.cut(1 - t, fromX, fromY, x1, y1, x2, y2, toX, toY)\n\n if (left && right) {\n smooth.push(C, left[0], left[1], left[2], left[3], left[4], left[5])\n arcTo(smooth, toX, toY, nextX, nextY, cornerRadius, left[4], left[5], three)\n } else {\n smooth.push(C, x1, y1, x2, y2, toX, toY)\n }\n}","import { Plugin } from '@leafer-ui/draw'\nimport './PathCorner'\n\n\nPlugin.add('corner')"],"names":["getTangentDistance","r","x","y","lastX","lastY","nextX","nextY","ux","uy","vx","vy","lenU","Math","sqrt","lenV","cosTheta","safeCos","max","min","d","maxD","getCorrectT","x1","y1","x2","y2","toX","toY","chordLen","pow","vx0","vy0","v0mag","t","tempP","i","BezierHelper","getPointAndSet","dx","dy","currentDist","f_prime","getDerivative","abs","nextT","safeNextT","M","L","C","Z","Command","getCenterX","getCenterY","PointHelper","arcTo","PathCommandDataHelper","findEndPoint","data","command","commandLen","len","length","PathNumberCommandLengthMap","setAfterC","cornerRadius","fromX","fromY","two","cut","left","right","setBeforeC","smooth","three","push","PathCorner","_cornerSmoothing","radius","lastCommand","isNeedConvert","PathConvert","toCanvasData","countCommand","startX","startY","startR","secondX","secondY","isArray","isUndefined","end","j","Plugin","add"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(e){"use strict";function t(e,t,a,r,n,s,c){const h=r-t,i=n-a,o=s-t,u=c-a,f=Math.sqrt(h*h+i*i),l=Math.sqrt(o*o+u*u);if(f<.001||l<.001)return 0;const p=(h*o+i*u)/(f*l),M=Math.max(-.99999,Math.min(.99999,p));let b=e*Math.sqrt((1-M)/(1+M));const m=Math.min(f/2,l/2);return Math.min(b,m)}function a(t,a,r,n,s,c,h,i,o){if(t<=0)return 0;const u=Math.sqrt(Math.pow(i-a,2)+Math.pow(o-r,2));if(t>=u)return.5;const f=3*(n-a),l=3*(s-r);let p=Math.sqrt(f*f+l*l);p<1e-6&&(p=u||1);let M=Math.min(.5,t/p);const b={x:0,y:0};for(let u=0;u<5;u++){e.BezierHelper.getPointAndSet(M,a,r,n,s,c,h,i,o,b);const u=b.x-a,f=b.y-r,l=Math.sqrt(u*u+f*f);if(l<1e-6){M*=1.5;continue}const p=(u*e.BezierHelper.getDerivative(M,a,n,c,i)+f*e.BezierHelper.getDerivative(M,r,s,h,o))/l;if(Math.abs(p)<1e-6)break;const m=M-(l-t)/p,k=Math.max(0,Math.min(.6,m));if(Math.abs(k-M)<1e-5){M=k;break}M=k}return Math.max(0,Math.min(.5,M))}const{M:r,L:n,C:s,Z:c}=e.PathCommandMap,{getCenterX:h,getCenterY:i}=e.PointHelper,{arcTo:o}=e.PathCommandDataHelper;function u(t,a){let h,i,o,u;const f=t.length;for(;a<f;)switch(h=t[a],h){case r:return;case n:o=t[a+1],u=t[a+2],a+=3;break;case s:o=t[a+5],u=t[a+6],a+=7;break;case c:return{x:o,y:u};default:i=e.PathNumberCommandLengthMap[h],a+=i}}function f(r,n,s,c,h,i,o,u,f,l,p,M,b){const m=a(t(s,i,o,c,h,u,f),i,o,u,f,l,p,M,b),k=e.BezierHelper.cut(m,i,o,u,f,l,p,M,b),{left:d,right:g}=k;return d&&g&&(r[n+1]=g[0],r[n+2]=g[1],r[n+3]=g[2],r[n+4]=g[3]),k}function l(r,n,c,h,i,u,f,l,p,M,b,m,k){const d=a(t(n,p,M,f,l,b,m),p,M,f,l,i,u,c,h),{left:g,right:C}=e.BezierHelper.cut(1-d,c,h,i,u,f,l,p,M);g&&C?(r.push(s,g[0],g[1],g[2],g[3],g[4],g[5]),o(r,p,M,b,m,n,g[4],g[5],k)):r.push(s,i,u,f,l,p,M)}e.PathCorner.smooth=function(t,a,p){const M=t.radius;let b,m,k;(function(e){let t,a=0;const h=e.length;for(;a<h;)switch(t=e[a],t){case r:case n:a+=3;break;case s:a+=7;break;case c:a+=1;break;default:return!0}return!1})(t)&&(t=e.PathConvert.toCanvasData(t,!0));let d,g,C,P,w,x,H,q=0,v=0,y=0,z=0,B=0,D=0,L=0,A=0,N=0,U=0,I=0;e.isArray(a)&&(a=a[0]||0);const S=t.length,T=9===S,X=[];for(;q<S;){switch(b=t[q],d=M?e.isUndefined(M[v])?a:M[v]:a,b){case r:B=U=t[q+1],D=I=t[q+2],L=d,q+=3;const a=u(t,q);switch(t[q]){case n:A=t[q+1],N=t[q+2],T?X.push(r,B,D):a?X.push(r,h(B,A),i(D,N)):X.push(r,B,D);break;case s:if(a){const{left:e,right:n}=f(t,q,d,a.x,a.y,B,D,t[q+1],t[q+2],t[q+3],t[q+4],t[q+5],t[q+6]);if(e&&n){X.push(r,A=e[4],N=e[5]);break}}default:X.push(r,A=B,N=D)}break;case n:switch(y=t[q+1],z=t[q+2],q+=3,t[q]){case n:o(X,y,z,t[q+1],t[q+2],d,U,I,T);break;case s:const{left:e,right:a}=f(t,q,d,U,I,y,z,t[q+1],t[q+2],t[q+3],t[q+4],t[q+5],t[q+6]);e&&a?o(X,y,z,e[4],e[5],d,U,I,T):X.push(n,y,z);break;case c:o(X,y,z,B,D,d,U,I,T);break;default:X.push(n,y,z)}U=y,I=z;break;case s:switch(g=t[q+1],C=t[q+2],P=t[q+3],w=t[q+4],y=t[q+5],z=t[q+6],q+=7,t[q]){case n:x=t[q+1],H=t[q+2],l(X,d,U,I,g,C,P,w,y,z,x,H,T);break;case s:X.push(s,g,C,P,w,y,z);break;case c:x=B,H=D,l(X,d,U,I,g,C,P,w,y,z,x,H,T)}U=y,I=z;break;case c:m!==c&&(o(X,B,D,A,N,L,U,I,T),X.push(c)),q+=1;break;default:k=e.PathNumberCommandLengthMap[b];for(let e=0;e<k;e++)X.push(t[q+e]);q+=k}m=b,v++}return X},e.Plugin.add("corner")}(LeaferUI);
|
|
2
|
+
//# sourceMappingURL=corner.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corner.min.js","sources":["../../../../../../src/in/packages/corner/src/helper.ts","../../../../../../src/in/packages/corner/src/PathCorner.ts","../../../../../../src/in/packages/corner/src/index.ts"],"sourcesContent":["import { BezierHelper } from '@leafer-ui/draw'\n\n\n// 获取圆角切线距离\nexport function getTangentDistance(r: number, x: number, y: number, lastX: number, lastY: number, nextX: number, nextY: number): number {\n // 1. 构造入射向量 U (P -> lastP) 和出射向量 V (P -> nextP)\n const ux = lastX - x, uy = lastY - y\n const vx = nextX - x, vy = nextY - y\n\n // 2. 计算向量长度(平方和开方)\n const lenU = Math.sqrt(ux * ux + uy * uy)\n const lenV = Math.sqrt(vx * vx + vy * vy)\n\n // 3. 边界防御:若线段长度几乎为0,则不产生圆角\n if (lenU < 0.001 || lenV < 0.001) return 0\n\n // 4. 计算向量夹角余弦值 cos(θ) = (U·V) / (|U|*|V|)\n const cosTheta = (ux * vx + uy * vy) / (lenU * lenV)\n\n // 5. 精度钳位:防止浮点误差导致 cos 越界 [-1, 1],避开分母为0的情况\n const safeCos = Math.max(-0.99999, Math.min(0.99999, cosTheta))\n\n // 6. 核心几何推导:d = r * sqrt((1 - cosθ) / (1 + cosθ))\n let d = r * Math.sqrt((1 - safeCos) / (1 + safeCos))\n\n // 7. 【关键性能与安全约束】:最大距离不得超过相邻边长的一半\n // 这样可以确保相邻顶点的圆角不会发生几何重叠或路径自交。\n const maxD = Math.min(lenU / 2, lenV / 2)\n return Math.min(d, maxD)\n}\n\n// 精准定位贝塞尔曲线参数 t\nexport function getCorrectT(d: number, x: number, y: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number): number {\n if (d <= 0) return 0\n\n // 1. 预估总弦长(起点到终点的直线距离)\n const chordLen = Math.sqrt((toX - x) ** 2 + (toY - y) ** 2)\n\n // 2. 边界保护:若要求的距离超过弦长,为了路径安全,强制限制在曲线 50% 处\n if (d >= chordLen) return 0.5\n\n // 3. 初始猜测值估算:利用 t=0 处的瞬时速度矢量 v(0) = 3*(P1 - P0)\n const vx0 = 3 * (x1 - x)\n const vy0 = 3 * (y1 - y)\n let v0mag = Math.sqrt(vx0 * vx0 + vy0 * vy0)\n\n // 【优化点】:若起点与控制点重合(初速度为0),降级使用弦长线性比例,防止 NaN\n if (v0mag < 1e-6) v0mag = chordLen || 1\n\n let t = Math.min(0.5, d / v0mag)\n const tempP = { x: 0, y: 0 }\n\n // 4. 牛顿迭代 (Newton-Raphson) 循环\n for (let i = 0; i < 5; i++) {\n // 获取当前参数 t 对应的坐标点\n BezierHelper.getPointAndSet(t, x, y, x1, y1, x2, y2, toX, toY, tempP)\n\n const dx = tempP.x - x\n const dy = tempP.y - y\n const currentDist = Math.sqrt(dx * dx + dy * dy)\n\n // 数值稳定性检查:若当前点过于靠近起点,尝试向外探测\n if (currentDist < 1e-6) {\n t = t * 1.5\n continue\n }\n\n // 计算当前 t 处的导数向量 (x', y')\n const vxt = BezierHelper.getDerivative(t, x, x1, x2, toX)\n const vyt = BezierHelper.getDerivative(t, y, y1, y2, toY)\n\n // 计算目标函数的导数 f'(t) = (dx*x' + dy*y') / currentDist\n const f_prime = (dx * vxt + dy * vyt) / currentDist\n\n // 如果导数过小,说明进入平台期或计算异常,停止迭代\n if (Math.abs(f_prime) < 1e-6) break\n\n // 牛顿法公式:t_next = t - f(t) / f'(t)\n const deltaT = (currentDist - d) / f_prime\n const nextT = t - deltaT\n\n // 【收敛域保护】:强制限制在 [0, 0.6] 范围内寻找最优解,防止迭代跳出贝塞尔曲线有效区间\n const safeNextT = Math.max(0, Math.min(0.6, nextT))\n\n // 精度满足 1e-5 (像素级精度) 提前退出\n if (Math.abs(safeNextT - t) < 1e-5) {\n t = safeNextT\n break\n }\n t = safeNextT\n }\n\n // 最终返回结果,上限截断在 0.5 处,确保圆弧不会占据整条曲线导致形状崩坏\n return Math.max(0, Math.min(0.5, t))\n}","import { IPathCommandData, IPathCommandDataWithRadius, IPointData } from '@leafer-ui/interface'\nimport { PathCorner, PointHelper, PathCommandMap as Command, PathNumberCommandLengthMap, isArray, isUndefined, PathCommandDataHelper, BezierHelper, PathConvert } from '@leafer-ui/draw'\n\nimport { getCorrectT, getTangentDistance } from './helper'\n\n\nconst { M, L, C, Z } = Command\nconst { getCenterX, getCenterY } = PointHelper\nconst { arcTo } = PathCommandDataHelper\n\nPathCorner.smooth = function smooth(data: IPathCommandData, cornerRadius: number, _cornerSmoothing?: number): IPathCommandData {\n\n const radius = (data as any as IPathCommandDataWithRadius).radius // 独立圆角\n if (isNeedConvert(data)) data = PathConvert.toCanvasData(data, true)\n\n let command: number, lastCommand: number, commandLen\n let i = 0, countCommand = 0, x = 0, y = 0, startX = 0, startY = 0, startR = 0, secondX = 0, secondY = 0, lastX = 0, lastY = 0, r: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number\n if (isArray(cornerRadius)) cornerRadius = cornerRadius[0] || 0\n\n const len = data.length, three = len === 9 // 3个点时可以加大圆角\n const smooth: IPathCommandData = []\n\n while (i < len) {\n command = data[i]\n r = radius ? (isUndefined(radius[countCommand]) ? cornerRadius : radius[countCommand]) : cornerRadius\n switch (command) {\n case M: //moveto(x, y)\n startX = lastX = data[i + 1]\n startY = lastY = data[i + 2]\n startR = r\n i += 3\n const end = findEndPoint(data, i)\n switch (data[i]) { // next command\n case L: // lineTo()\n secondX = data[i + 1]\n secondY = data[i + 2]\n if (three) smooth.push(M, startX, startY)\n else {\n if (end) smooth.push(M, getCenterX(startX, secondX), getCenterY(startY, secondY))\n else smooth.push(M, startX, startY)\n }\n break\n case C: // bezierCurveTo()\n if (end) {\n const { left, right } = setAfterC(data, i, r, end.x, end.y, startX, startY, data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6])\n if (left && right) {\n smooth.push(M, secondX = left[4], secondY = left[5])\n break\n }\n }\n default:\n smooth.push(M, secondX = startX, secondY = startY)\n }\n break\n case L: //lineto(x, y)\n x = data[i + 1]\n y = data[i + 2]\n i += 3\n switch (data[i]) { // next command\n case L: // lineTo()\n arcTo(smooth, x, y, data[i + 1], data[i + 2], r, lastX, lastY, three) // use arcTo(x1, y1, x2, y2, radius)\n break\n case C: // bezierCurveTo()\n const { left, right } = setAfterC(data, i, r, lastX, lastY, x, y, data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6])\n if (left && right) arcTo(smooth, x, y, left[4], left[5], r, lastX, lastY, three)\n else smooth.push(L, x, y)\n break\n case Z: // closePath()\n arcTo(smooth, x, y, startX, startY, r, lastX, lastY, three) // use arcTo(x1, y1, x2, y2, radius)\n break\n default:\n smooth.push(L, x, y)\n }\n lastX = x\n lastY = y\n break\n case C:\n x1 = data[i + 1]\n y1 = data[i + 2]\n x2 = data[i + 3]\n y2 = data[i + 4]\n x = data[i + 5]\n y = data[i + 6]\n i += 7\n switch (data[i]) { // next command\n case L: // lineTo()\n toX = data[i + 1], toY = data[i + 2]\n setBeforeC(smooth, r, lastX, lastY, x1, y1, x2, y2, x, y, toX, toY, three)\n break\n case C: //\n smooth.push(C, x1, y1, x2, y2, x, y)\n break\n case Z: // closePath()\n toX = startX, toY = startY\n setBeforeC(smooth, r, lastX, lastY, x1, y1, x2, y2, x, y, toX, toY, three)\n break\n }\n lastX = x\n lastY = y\n break\n case Z: //closepath()\n if (lastCommand !== Z) { // fix: 重复的 Z 导致的问题\n arcTo(smooth, startX, startY, secondX, secondY, startR, lastX, lastY, three) // use arcTo(x1, y1, x2, y2, radius)\n smooth.push(Z)\n }\n i += 1\n break\n default:\n commandLen = PathNumberCommandLengthMap[command]\n for (let j = 0; j < commandLen; j++) smooth.push(data[i + j])\n i += commandLen\n }\n lastCommand = command\n countCommand++\n }\n\n return smooth\n}\n\n\nfunction isNeedConvert(data: IPathCommandData): boolean {\n let command: number, i = 0\n const len = data.length\n while (i < len) {\n command = data[i]\n switch (command) {\n case M: //moveto(x, y)\n i += 3\n break\n case L: //lineto(x, y)\n i += 3\n break\n case C: // bezierCurveTo()\n i += 7\n break\n case Z: //closepath()\n i += 1\n break\n default:\n return true\n }\n }\n return false\n}\n\nfunction findEndPoint(data: IPathCommandData, i: number): IPointData {\n let command: number, commandLen: number, x: number, y: number\n const len = data.length\n while (i < len) {\n command = data[i]\n switch (command) {\n case M: //moveto(x, y)\n return undefined\n case L: //lineto(x, y)\n x = data[i + 1]\n y = data[i + 2]\n i += 3\n break\n case C: // bezierCurveTo()\n x = data[i + 5]\n y = data[i + 6]\n i += 7\n break\n case Z: //closepath()\n return { x, y }\n default:\n commandLen = PathNumberCommandLengthMap[command]\n i += commandLen\n }\n }\n return undefined\n}\n\n\nfunction setAfterC(data: IPathCommandData, i: number, cornerRadius: number, lastX: number, lastY: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number) {\n const d = getTangentDistance(cornerRadius, fromX, fromY, lastX, lastY, x1, y1)\n const t = getCorrectT(d, fromX, fromY, x1, y1, x2, y2, toX, toY)\n const two = BezierHelper.cut(t, fromX, fromY, x1, y1, x2, y2, toX, toY)\n const { left, right } = two\n\n if (left && right) {\n data[i + 1] = right[0]; data[i + 2] = right[1]\n data[i + 3] = right[2]; data[i + 4] = right[3]\n }\n\n return two\n}\n\nfunction setBeforeC(smooth: IPathCommandData, cornerRadius: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number, nextX: number, nextY: number, three: boolean) {\n const d = getTangentDistance(cornerRadius, toX, toY, x2, y2, nextX, nextY) // 反向\n const t = getCorrectT(d, toX, toY, x2, y2, x1, y1, fromX, fromY) // 反向\n const { left, right } = BezierHelper.cut(1 - t, fromX, fromY, x1, y1, x2, y2, toX, toY)\n\n if (left && right) {\n smooth.push(C, left[0], left[1], left[2], left[3], left[4], left[5])\n arcTo(smooth, toX, toY, nextX, nextY, cornerRadius, left[4], left[5], three)\n } else {\n smooth.push(C, x1, y1, x2, y2, toX, toY)\n }\n}","import { Plugin } from '@leafer-ui/draw'\nimport './PathCorner'\n\n\nPlugin.add('corner')"],"names":["getTangentDistance","r","x","y","lastX","lastY","nextX","nextY","ux","uy","vx","vy","lenU","Math","sqrt","lenV","cosTheta","safeCos","max","min","d","maxD","getCorrectT","x1","y1","x2","y2","toX","toY","chordLen","pow","vx0","vy0","v0mag","t","tempP","i","BezierHelper","getPointAndSet","dx","dy","currentDist","f_prime","getDerivative","abs","nextT","safeNextT","M","L","C","Z","Command","getCenterX","getCenterY","PointHelper","arcTo","PathCommandDataHelper","findEndPoint","data","command","commandLen","len","length","PathNumberCommandLengthMap","setAfterC","cornerRadius","fromX","fromY","two","cut","left","right","setBeforeC","smooth","three","push","PathCorner","_cornerSmoothing","radius","lastCommand","isNeedConvert","PathConvert","toCanvasData","countCommand","startX","startY","startR","secondX","secondY","isArray","isUndefined","end","j","Plugin","add"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@leafer-in/corner",
|
|
3
|
+
"version": "2.0.7",
|
|
4
|
+
"description": "@leafer-in/corner",
|
|
5
|
+
"author": "Chao (Leafer) Wan",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/corner.esm.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
"import": "./dist/corner.esm.min.js",
|
|
11
|
+
"require": "./dist/corner.min.cjs",
|
|
12
|
+
"types": "./types/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"types": "types/index.d.ts",
|
|
15
|
+
"unpkg": "dist/corner.min.js",
|
|
16
|
+
"jsdelivr": "dist/corner.min.js",
|
|
17
|
+
"files": [
|
|
18
|
+
"src",
|
|
19
|
+
"types",
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/leaferjs/leafer-in.git"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/leaferjs/leafer-in/tree/main/packages/corner",
|
|
27
|
+
"bugs": "https://github.com/leaferjs/leafer-in/issues",
|
|
28
|
+
"keywords": [
|
|
29
|
+
"leafer corner",
|
|
30
|
+
"leafer-corner",
|
|
31
|
+
"leafer-in",
|
|
32
|
+
"corner",
|
|
33
|
+
"leafer-ui",
|
|
34
|
+
"leaferjs"
|
|
35
|
+
],
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"@leafer-ui/draw": "^2.0.7",
|
|
38
|
+
"@leafer-ui/interface": "^2.0.7",
|
|
39
|
+
"@leafer-in/interface": "^2.0.7"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { IPathCommandData, IPathCommandDataWithRadius, IPointData } from '@leafer-ui/interface'
|
|
2
|
+
import { PathCorner, PointHelper, PathCommandMap as Command, PathNumberCommandLengthMap, isArray, isUndefined, PathCommandDataHelper, BezierHelper, PathConvert } from '@leafer-ui/draw'
|
|
3
|
+
|
|
4
|
+
import { getCorrectT, getTangentDistance } from './helper'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const { M, L, C, Z } = Command
|
|
8
|
+
const { getCenterX, getCenterY } = PointHelper
|
|
9
|
+
const { arcTo } = PathCommandDataHelper
|
|
10
|
+
|
|
11
|
+
PathCorner.smooth = function smooth(data: IPathCommandData, cornerRadius: number, _cornerSmoothing?: number): IPathCommandData {
|
|
12
|
+
|
|
13
|
+
const radius = (data as any as IPathCommandDataWithRadius).radius // 独立圆角
|
|
14
|
+
if (isNeedConvert(data)) data = PathConvert.toCanvasData(data, true)
|
|
15
|
+
|
|
16
|
+
let command: number, lastCommand: number, commandLen
|
|
17
|
+
let i = 0, countCommand = 0, x = 0, y = 0, startX = 0, startY = 0, startR = 0, secondX = 0, secondY = 0, lastX = 0, lastY = 0, r: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number
|
|
18
|
+
if (isArray(cornerRadius)) cornerRadius = cornerRadius[0] || 0
|
|
19
|
+
|
|
20
|
+
const len = data.length, three = len === 9 // 3个点时可以加大圆角
|
|
21
|
+
const smooth: IPathCommandData = []
|
|
22
|
+
|
|
23
|
+
while (i < len) {
|
|
24
|
+
command = data[i]
|
|
25
|
+
r = radius ? (isUndefined(radius[countCommand]) ? cornerRadius : radius[countCommand]) : cornerRadius
|
|
26
|
+
switch (command) {
|
|
27
|
+
case M: //moveto(x, y)
|
|
28
|
+
startX = lastX = data[i + 1]
|
|
29
|
+
startY = lastY = data[i + 2]
|
|
30
|
+
startR = r
|
|
31
|
+
i += 3
|
|
32
|
+
const end = findEndPoint(data, i)
|
|
33
|
+
switch (data[i]) { // next command
|
|
34
|
+
case L: // lineTo()
|
|
35
|
+
secondX = data[i + 1]
|
|
36
|
+
secondY = data[i + 2]
|
|
37
|
+
if (three) smooth.push(M, startX, startY)
|
|
38
|
+
else {
|
|
39
|
+
if (end) smooth.push(M, getCenterX(startX, secondX), getCenterY(startY, secondY))
|
|
40
|
+
else smooth.push(M, startX, startY)
|
|
41
|
+
}
|
|
42
|
+
break
|
|
43
|
+
case C: // bezierCurveTo()
|
|
44
|
+
if (end) {
|
|
45
|
+
const { left, right } = setAfterC(data, i, r, end.x, end.y, startX, startY, data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6])
|
|
46
|
+
if (left && right) {
|
|
47
|
+
smooth.push(M, secondX = left[4], secondY = left[5])
|
|
48
|
+
break
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
default:
|
|
52
|
+
smooth.push(M, secondX = startX, secondY = startY)
|
|
53
|
+
}
|
|
54
|
+
break
|
|
55
|
+
case L: //lineto(x, y)
|
|
56
|
+
x = data[i + 1]
|
|
57
|
+
y = data[i + 2]
|
|
58
|
+
i += 3
|
|
59
|
+
switch (data[i]) { // next command
|
|
60
|
+
case L: // lineTo()
|
|
61
|
+
arcTo(smooth, x, y, data[i + 1], data[i + 2], r, lastX, lastY, three) // use arcTo(x1, y1, x2, y2, radius)
|
|
62
|
+
break
|
|
63
|
+
case C: // bezierCurveTo()
|
|
64
|
+
const { left, right } = setAfterC(data, i, r, lastX, lastY, x, y, data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6])
|
|
65
|
+
if (left && right) arcTo(smooth, x, y, left[4], left[5], r, lastX, lastY, three)
|
|
66
|
+
else smooth.push(L, x, y)
|
|
67
|
+
break
|
|
68
|
+
case Z: // closePath()
|
|
69
|
+
arcTo(smooth, x, y, startX, startY, r, lastX, lastY, three) // use arcTo(x1, y1, x2, y2, radius)
|
|
70
|
+
break
|
|
71
|
+
default:
|
|
72
|
+
smooth.push(L, x, y)
|
|
73
|
+
}
|
|
74
|
+
lastX = x
|
|
75
|
+
lastY = y
|
|
76
|
+
break
|
|
77
|
+
case C:
|
|
78
|
+
x1 = data[i + 1]
|
|
79
|
+
y1 = data[i + 2]
|
|
80
|
+
x2 = data[i + 3]
|
|
81
|
+
y2 = data[i + 4]
|
|
82
|
+
x = data[i + 5]
|
|
83
|
+
y = data[i + 6]
|
|
84
|
+
i += 7
|
|
85
|
+
switch (data[i]) { // next command
|
|
86
|
+
case L: // lineTo()
|
|
87
|
+
toX = data[i + 1], toY = data[i + 2]
|
|
88
|
+
setBeforeC(smooth, r, lastX, lastY, x1, y1, x2, y2, x, y, toX, toY, three)
|
|
89
|
+
break
|
|
90
|
+
case C: //
|
|
91
|
+
smooth.push(C, x1, y1, x2, y2, x, y)
|
|
92
|
+
break
|
|
93
|
+
case Z: // closePath()
|
|
94
|
+
toX = startX, toY = startY
|
|
95
|
+
setBeforeC(smooth, r, lastX, lastY, x1, y1, x2, y2, x, y, toX, toY, three)
|
|
96
|
+
break
|
|
97
|
+
}
|
|
98
|
+
lastX = x
|
|
99
|
+
lastY = y
|
|
100
|
+
break
|
|
101
|
+
case Z: //closepath()
|
|
102
|
+
if (lastCommand !== Z) { // fix: 重复的 Z 导致的问题
|
|
103
|
+
arcTo(smooth, startX, startY, secondX, secondY, startR, lastX, lastY, three) // use arcTo(x1, y1, x2, y2, radius)
|
|
104
|
+
smooth.push(Z)
|
|
105
|
+
}
|
|
106
|
+
i += 1
|
|
107
|
+
break
|
|
108
|
+
default:
|
|
109
|
+
commandLen = PathNumberCommandLengthMap[command]
|
|
110
|
+
for (let j = 0; j < commandLen; j++) smooth.push(data[i + j])
|
|
111
|
+
i += commandLen
|
|
112
|
+
}
|
|
113
|
+
lastCommand = command
|
|
114
|
+
countCommand++
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return smooth
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
function isNeedConvert(data: IPathCommandData): boolean {
|
|
122
|
+
let command: number, i = 0
|
|
123
|
+
const len = data.length
|
|
124
|
+
while (i < len) {
|
|
125
|
+
command = data[i]
|
|
126
|
+
switch (command) {
|
|
127
|
+
case M: //moveto(x, y)
|
|
128
|
+
i += 3
|
|
129
|
+
break
|
|
130
|
+
case L: //lineto(x, y)
|
|
131
|
+
i += 3
|
|
132
|
+
break
|
|
133
|
+
case C: // bezierCurveTo()
|
|
134
|
+
i += 7
|
|
135
|
+
break
|
|
136
|
+
case Z: //closepath()
|
|
137
|
+
i += 1
|
|
138
|
+
break
|
|
139
|
+
default:
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return false
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function findEndPoint(data: IPathCommandData, i: number): IPointData {
|
|
147
|
+
let command: number, commandLen: number, x: number, y: number
|
|
148
|
+
const len = data.length
|
|
149
|
+
while (i < len) {
|
|
150
|
+
command = data[i]
|
|
151
|
+
switch (command) {
|
|
152
|
+
case M: //moveto(x, y)
|
|
153
|
+
return undefined
|
|
154
|
+
case L: //lineto(x, y)
|
|
155
|
+
x = data[i + 1]
|
|
156
|
+
y = data[i + 2]
|
|
157
|
+
i += 3
|
|
158
|
+
break
|
|
159
|
+
case C: // bezierCurveTo()
|
|
160
|
+
x = data[i + 5]
|
|
161
|
+
y = data[i + 6]
|
|
162
|
+
i += 7
|
|
163
|
+
break
|
|
164
|
+
case Z: //closepath()
|
|
165
|
+
return { x, y }
|
|
166
|
+
default:
|
|
167
|
+
commandLen = PathNumberCommandLengthMap[command]
|
|
168
|
+
i += commandLen
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return undefined
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
function setAfterC(data: IPathCommandData, i: number, cornerRadius: number, lastX: number, lastY: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number) {
|
|
176
|
+
const d = getTangentDistance(cornerRadius, fromX, fromY, lastX, lastY, x1, y1)
|
|
177
|
+
const t = getCorrectT(d, fromX, fromY, x1, y1, x2, y2, toX, toY)
|
|
178
|
+
const two = BezierHelper.cut(t, fromX, fromY, x1, y1, x2, y2, toX, toY)
|
|
179
|
+
const { left, right } = two
|
|
180
|
+
|
|
181
|
+
if (left && right) {
|
|
182
|
+
data[i + 1] = right[0]; data[i + 2] = right[1]
|
|
183
|
+
data[i + 3] = right[2]; data[i + 4] = right[3]
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return two
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function setBeforeC(smooth: IPathCommandData, cornerRadius: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number, nextX: number, nextY: number, three: boolean) {
|
|
190
|
+
const d = getTangentDistance(cornerRadius, toX, toY, x2, y2, nextX, nextY) // 反向
|
|
191
|
+
const t = getCorrectT(d, toX, toY, x2, y2, x1, y1, fromX, fromY) // 反向
|
|
192
|
+
const { left, right } = BezierHelper.cut(1 - t, fromX, fromY, x1, y1, x2, y2, toX, toY)
|
|
193
|
+
|
|
194
|
+
if (left && right) {
|
|
195
|
+
smooth.push(C, left[0], left[1], left[2], left[3], left[4], left[5])
|
|
196
|
+
arcTo(smooth, toX, toY, nextX, nextY, cornerRadius, left[4], left[5], three)
|
|
197
|
+
} else {
|
|
198
|
+
smooth.push(C, x1, y1, x2, y2, toX, toY)
|
|
199
|
+
}
|
|
200
|
+
}
|