1
- const postcss = require ( 'postcss' ) ;
2
- const valueParser = require ( 'postcss-value-parser' ) ;
3
- const tinyColor = require ( 'tinycolor2' ) ;
1
+ const postcss = require ( 'postcss' ) ;
2
+ const valueParser = require ( 'postcss-value-parser' ) ;
3
+ const tinyColor = require ( 'tinycolor2' ) ;
4
+ const easeInSine = require ( 'eases/sine-in' ) ;
5
+ const easeOutSine = require ( 'eases/sine-out' ) ;
6
+ const easeInOutSine = require ( 'eases/sine-in-out' ) ;
7
+ const easeInQuad = require ( 'eases/quad-in' ) ;
8
+ const easeOutQuad = require ( 'eases/quad-out' ) ;
9
+ const easeInOutQuad = require ( 'eases/quad-in-out' ) ;
4
10
5
11
const supportedGradients = [
6
12
'ease-in-sine-gradient' ,
@@ -12,6 +18,22 @@ const supportedGradients = [
12
18
'scrim-gradient'
13
19
] ;
14
20
21
+ const scrimCoordinates = {
22
+ 0.00 : '0%' ,
23
+ 0.14 : '8.52%' ,
24
+ 0.28 : '17.53%' ,
25
+ 0.42 : '27.19%' ,
26
+ 0.54 : '36.28%' ,
27
+ 0.64 : '44.56%' ,
28
+ 0.72 : '51.97%' ,
29
+ 0.79 : '59.18%' ,
30
+ 0.85 : '66.33%' ,
31
+ 0.90 : '73.39%' ,
32
+ 0.94 : '80.36%' ,
33
+ 0.97 : '87.18%' ,
34
+ 0.99 : '93.73%'
35
+ }
36
+
15
37
/**
16
38
* The easing gradient function is a postcss plugin which supports the above
17
39
* mentioned gradient types.
@@ -100,23 +122,15 @@ function functionToWord(obj) {
100
122
*/
101
123
function getColorStops ( colors , easingType ) {
102
124
colors = transparentFix ( colors ) ;
125
+ let gradientCoordinates = getCoordinates ( easingType ) ;
103
126
let colorStops = '' ;
104
- if ( easingType === 'scrim-gradient' ) {
105
- for ( let ammount in scrimMap ) {
106
- let color = tinyColor
107
- . mix ( colors [ 0 ] , colors [ 1 ] , ammount )
108
- . toHslString ( ) ;
109
- colorStops += `, ${ color } ${ scrimMap [ ammount ] } ` ;
110
- }
111
- } else {
112
- for ( let stopValue of stopsArray ( 15 ) ) {
113
- let color = tinyColor
114
- . mix ( colors [ 0 ] , colors [ 1 ] , 100 * ease ( stopValue , easingType ) )
115
- . toHslString ( ) ;
116
- let percent = getPercentage ( stopValue ) ;
117
- colorStops += `, ${ color } ${ percent } ` ;
118
- }
127
+ for ( let ammount in gradientCoordinates ) {
128
+ let color = tinyColor
129
+ . mix ( colors [ 0 ] , colors [ 1 ] , ammount * 100 )
130
+ . toHslString ( ) ;
131
+ colorStops += `, ${ color } ${ gradientCoordinates [ ammount ] } ` ;
119
132
}
133
+ colorStops += `, ${ colors [ 1 ] } 100%` ;
120
134
return colorStops ;
121
135
} ;
122
136
@@ -140,44 +154,72 @@ function transparentToAlpha(colors, color) {
140
154
}
141
155
142
156
/**
143
- * Function to generate an array with values that are linear divisions of 1
144
- * E.g. [0, 0.25, 0.5, 0.75, 1]
157
+ * Get coordinates based on easing function.
158
+ * The delta checks ensures there's roughly the same distance between each
159
+ * coordinate.
145
160
*/
146
- function stopsArray ( stopCount ) {
147
- let array = [ ] ;
148
- let value = 0 ;
149
- let i = 0 ;
150
- while ( i <= stopCount ) {
151
- array . push ( value ) ;
152
- value += 1 / stopCount ;
153
- i += 1 ;
161
+ function getCoordinates ( easingFunction ) {
162
+ if ( easingFunction === 'scrim-gradient' ) return scrimCoordinates ;
163
+
164
+ const yIncrements = 0.001 ;
165
+ const deltaTolerance = 0.01 ;
166
+ const deltaAdjust = 0.001 ;
167
+
168
+ let delta = 0.1 ;
169
+ let coordinates = { } ;
170
+ let x = 0 ;
171
+ let y = 0 ;
172
+ let xOld = 0 ;
173
+ let yOld = 0 ;
174
+ let firstTime = true ;
175
+
176
+ while ( firstTime || ! isDelta ( 1 , 1 , xOld , yOld , delta - deltaTolerance ) ) {
177
+ if ( firstTime ) {
178
+ firstTime = false ;
179
+ } else {
180
+ x = 0 ;
181
+ y = 0 ;
182
+ xOld = 0 ;
183
+ yOld = 0 ;
184
+ delta = delta - deltaAdjust ;
185
+ coordinates = { } ;
186
+ }
187
+ while ( y <= 1 ) {
188
+ coordinates [ 0 ] = 0 ;
189
+ x = ease ( y , easingFunction ) ;
190
+ if ( isDelta ( x , y , xOld , yOld , delta ) ) {
191
+ coordinates [ x ] = getPercentage ( y ) ;
192
+ xOld = x ;
193
+ yOld = y ;
194
+ }
195
+ y += yIncrements ;
196
+ }
154
197
}
155
- return array ;
198
+ return coordinates ;
156
199
}
157
200
158
201
/**
159
- * Easing functions
160
- * https://gist.github.com/gre/1650294
202
+ * Easing functions switcheroo
161
203
*/
162
204
function ease ( x , type ) {
163
205
switch ( type ) {
164
206
case 'ease-in-sine-gradient' :
165
- return - 1 * Math . cos ( x * ( Math . PI / 2 ) ) + 1 ;
207
+ return easeInSine ( x ) ;
166
208
break ;
167
209
case 'ease-out-sine-gradient' :
168
- return Math . sin ( x * ( Math . PI / 2 ) ) ;
210
+ return easeOutSine ( x ) ;
169
211
break ;
170
212
case 'ease-in-out-sine-gradient' :
171
- return - 0.5 * ( Math . cos ( Math . PI * x ) - 1 ) ;
213
+ return easeInOutSine ( x ) ;
172
214
break ;
173
215
case 'ease-in-quad-gradient' :
174
- return x * x ;
216
+ return easeInQuad ( x ) ;
175
217
break ;
176
218
case 'ease-out-quad-gradient' :
177
- return x * ( 2 - x ) ;
219
+ return easeOutQuad ( x ) ;
178
220
break ;
179
221
case 'ease-in-out-quad-gradient' :
180
- return x < .5 ? 2 * x * x : - 1 + ( 4 - 2 * x ) * x ;
222
+ return easeInOutQuad ( x ) ;
181
223
break ;
182
224
default :
183
225
console . log ( `Sorry, easing gradient does not support ${ type } .` ) ;
@@ -191,19 +233,9 @@ function getPercentage (num) {
191
233
return parseFloat ( ( num * 100 ) . toFixed ( 3 ) ) + '%' ;
192
234
}
193
235
194
- const scrimMap = {
195
- 0 : '0%' ,
196
- 14 : '8.52%' ,
197
- 28 : '17.53%' ,
198
- 42 : '27.19%' ,
199
- 54 : '36.28%' ,
200
- 64 : '44.56%' ,
201
- 72 : '51.97%' ,
202
- 79 : '59.18%' ,
203
- 85 : '66.33%' ,
204
- 90 : '73.39%' ,
205
- 94 : '80.36%' ,
206
- 97 : '87.18%' ,
207
- 99 : '93.73%' ,
208
- 100 : '100%'
236
+ /**
237
+ * Test is new coordinate is far enough away from old coordinate
238
+ */
239
+ function isDelta ( x , y , xOld , yOld , delta ) {
240
+ return Math . sqrt ( ( x - xOld ) ** 2 + ( y - yOld ) ** 2 ) > delta ;
209
241
}
0 commit comments