@@ -55,7 +55,83 @@ class SmoothCornersPainter {
55
55
ctx . closePath ( )
56
56
ctx . fill ( )
57
57
}
58
+ }
59
+
60
+ class SmoothCornerPainterV2 {
61
+ static get inputProperties ( ) {
62
+ return [ '--smooth-corners' , '--smooth-corners-radius' , '--smooth-corners-steps' ]
63
+ }
64
+
65
+
66
+ superellipse ( a , b , nX = 4 , nY , steps = 360 ) {
67
+ if ( Number . isNaN ( nX ) ) nX = 4
68
+ if ( typeof nY === 'undefined' || Number . isNaN ( nY ) ) nY = nX
69
+ if ( nX > 100 ) nX = 100
70
+ if ( nY > 100 ) nY = 100
71
+ if ( nX < 0.00000000001 ) nX = 0.00000000001
72
+ if ( nY < 0.00000000001 ) nY = 0.00000000001
73
+
74
+ const nX2 = 2 / nX
75
+ const nY2 = nY ? 2 / nY : nX2
76
+ const step = ( 2 * Math . PI ) / steps
77
+ const points = t => {
78
+ const cosT = Math . cos ( t )
79
+ const sinT = Math . sin ( t )
80
+ return {
81
+ x : Math . abs ( cosT ) ** nX2 * a * Math . sign ( cosT ) ,
82
+ y : Math . abs ( sinT ) ** nY2 * b * Math . sign ( sinT )
83
+ }
84
+ }
85
+ return Array . from ( { length : steps } , ( _ , i ) => points ( i * step ) )
86
+ }
87
+
88
+ paint ( ctx , size , props ) {
89
+
90
+ const [ nX , nY ] = props
91
+ . get ( '--smooth-corners' )
92
+ . toString ( )
93
+ . replace ( / / g, '' )
94
+ . split ( ',' )
95
+ . map ( parseFloat )
96
+
97
+ const halfWidth = size . width / 2
98
+ const halfHeight = size . height / 2
99
+ const cornerRadius = Math . min ( parseFloat ( props . get ( '--smooth-corner-radius' ) ) || size . width / 2 , size . height / 2 , size . width / 2 )
100
+ const steps = parseFloat ( props . get ( '--smooth-corner-steps' ) ) || 360
101
+ const smoothCorners = this . superellipse (
102
+ cornerRadius ,
103
+ cornerRadius ,
104
+ nX ,
105
+ nY ,
106
+ steps
107
+ )
108
+
109
+ const xOffset = halfWidth - cornerRadius
110
+ const yOffset = halfHeight - cornerRadius
111
+
112
+ const leftBottomCorners = smoothCorners . slice ( 0 , steps / 4 ) . map ( ( { x, y } ) => ( { x : x + xOffset , y : y + yOffset } ) )
113
+ const rightBottomCorners = smoothCorners . slice ( steps / 4 , steps / 2 ) . map ( ( { x, y } ) => ( { x : x - xOffset , y : y + yOffset } ) )
114
+ const rightTopCorners = smoothCorners . slice ( steps / 2 , steps * 3 / 4 ) . map ( ( { x, y } ) => ( { x : x - xOffset , y : y - yOffset } ) )
115
+ const leftTopCorners = smoothCorners . slice ( steps * 3 / 4 , steps ) . map ( ( { x, y } ) => ( { x : x + xOffset , y : y - yOffset } ) )
116
+ const points = [ ...leftBottomCorners , ...rightBottomCorners , ...rightTopCorners , ...leftTopCorners ]
117
+
118
+ ctx . fillStyle = '#000'
119
+ ctx . setTransform ( 1 , 0 , 0 , 1 , halfWidth , halfHeight )
120
+ ctx . beginPath ( )
121
+ points . forEach ( ( { x, y } , i ) => {
122
+ if ( i === 0 ) ctx . moveTo ( x , y )
123
+ else ctx . lineTo ( x , y )
124
+ } )
125
+ ctx . closePath ( )
126
+ ctx . fill ( )
127
+
128
+ }
129
+
130
+
131
+
132
+
58
133
}
59
134
60
135
// eslint-disable-next-line no-undef
61
136
registerPaint ( 'smooth-corners' , SmoothCornersPainter )
137
+ registerPaint ( 'smooth-corners-v2' , SmoothCornerPainterV2 )
0 commit comments