22 TODO: write tests (lazy) like always right? <3
33*/
44const parser = require ( "gradient-parser" ) ;
5+ const memoize = require ( "fast-memoize" ) ;
56
67const getColor = color => {
78 switch ( color . type ) {
@@ -14,27 +15,23 @@ const getColor = color => {
1415 }
1516} ;
1617
17- const getColorsAndLocations = ( colorStops , maxWidth ) =>
18+ const getColorsAndLocations = memoize ( ( colorStops , maxWidth ) =>
1819 colorStops . reduce (
1920 ( acc , color , index ) => {
2021 acc . colors = [ ...acc . colors , getColor ( color ) ] ;
2122
2223 // PX value for location will break!
2324 // TODO Make it happen for px + repeat?
24- const locationValue = getPixelsForColor (
25- color ,
26- colorStops . length ,
27- index ,
28- maxWidth
29- ) ;
25+ const locationValue = getPixelsForColor ( color , colorStops . length , index , maxWidth ) ;
3026 acc [ "locations" ] = [ ...acc . locations , locationValue ] ;
3127
3228 return acc ;
3329 } ,
3430 { colors : [ ] , locations : [ ] }
35- ) ;
31+ )
32+ ) ;
3633
37- const getPixelsForColor = ( color , colorsLength , index , maxWidth ) => {
34+ const getPixelsForColor = memoize ( ( color , colorsLength , index , maxWidth ) => {
3835 const { length } = color ;
3936 if ( ! length ) {
4037 return ( 1 / ( colorsLength - 1 ) ) * index ;
@@ -49,33 +46,30 @@ const getPixelsForColor = (color, colorsLength, index, maxWidth) => {
4946 return length . value / 100 ;
5047 }
5148 }
52- } ;
49+ } ) ;
50+
5351const getRepeatingColorsAndLocations = ( colorStops , sizes ) => {
5452 const { width : maxWidth , height : maxHeight } = sizes ;
55-
56- if ( ! maxWidth && ! maxHeight ) {
57- throw new Error (
58- "You have to define width and height for repeating gradient to work"
59- ) ;
60- }
61-
62- const {
63- colors : initialColors ,
64- locations : initialLocations
65- } = getColorsAndLocations ( colorStops , maxWidth ) ;
53+ const { colors : initialColors , locations : initialLocations } = getColorsAndLocations ( colorStops , maxWidth ) ;
6654 const maxValue = parseFloat ( initialLocations . slice ( - 1 ) [ 0 ] ) ;
6755 const increment = maxValue / maxWidth ;
68- const maxChunks = Math . round ( maxWidth / maxValue ) + 1 ;
56+ // we need to add +1 but this is breaking LinearGradient, maybe can't render
57+ // it outside the viewport.
58+ const maxChunks = Math . round ( maxWidth / maxValue ) ;
6959 const locations = [ ...Array ( maxChunks ) . keys ( ) ] . reduce ( ( acc , i ) => {
70- return [ ...acc , ...initialLocations . map ( j => j / maxWidth + increment * i ) ] ;
60+ return [
61+ ...acc ,
62+ ...initialLocations . map ( j => {
63+ return j / maxWidth + increment * i ;
64+ } )
65+ ] ;
7166 } , [ ] ) ;
72- const colors = locations . map (
73- ( _ , i ) => initialColors [ i % initialColors . length ]
74- ) ;
67+ const colors = locations . map ( ( _ , i ) => initialColors [ i % initialColors . length ] ) ;
7568
76- return { locations , colors } ;
69+ return { colors , locations } ;
7770} ;
78- const getVectorsByDirection = direction => {
71+
72+ const getVectorsByDirection = memoize ( direction => {
7973 switch ( direction ) {
8074 case "top" :
8175 return getVectorsByAngle ( 0 ) ;
@@ -94,35 +88,39 @@ const getVectorsByDirection = direction => {
9488 case "right bottom" :
9589 return getVectorsByAngle ( 90 + 45 ) ;
9690 }
97- } ;
98- const round = number => Math . round ( number * 1000 ) / 1000 ;
99- const degreesToRadians = function ( degrees ) {
100- return ( degrees * Math . PI ) / 180 ;
101- } ;
102- const getVectorsByAngle = alfa => {
91+ } ) ;
92+
93+ const round = memoize ( number => Math . round ( number * 10000 ) / 10000 ) ;
94+ const degreesToRadians = memoize ( degrees => ( degrees * Math . PI ) / 180 ) ;
95+
96+ const getVectorsByAngle = memoize ( alfa => {
10397 const angle = degreesToRadians ( alfa ) ;
10498
105- let gradientLineLength = round (
106- Math . abs ( Math . sin ( angle ) ) + Math . abs ( Math . cos ( angle ) )
107- ) ;
99+ let gradientLineLength = round ( Math . abs ( Math . sin ( angle ) ) + Math . abs ( Math . cos ( angle ) ) ) ;
108100 let center = { x : 0.5 , y : 0.5 } ;
109101
110102 let yDiff = ( Math . sin ( angle - Math . PI / 2 ) * gradientLineLength ) / 2 ;
111103 let xDiff = ( Math . cos ( angle - Math . PI / 2 ) * gradientLineLength ) / 2 ;
112104
113105 return {
114- start : [ center . x - xDiff , center . y - yDiff ] ,
115- end : [ center . x + xDiff , center . y + yDiff ]
106+ start : {
107+ x : center . x - xDiff ,
108+ y : center . y - yDiff
109+ } ,
110+ end : {
111+ x : center . x + xDiff ,
112+ y : center . y + yDiff
113+ }
116114 } ;
117- } ;
115+ } ) ;
118116
119117const getVectorsByOrientation = orientation => {
120118 return orientation . type === "directional"
121119 ? getVectorsByDirection ( orientation . value )
122120 : getVectorsByAngle ( orientation . value ) ;
123121} ;
124122
125- const generateGradient = ( gradient , sizes ) => {
123+ const generateGradient = memoize ( ( gradient , sizes ) => {
126124 return parser . parse ( gradient ) . map ( ( { type, colorStops, orientation } ) => {
127125 // YOLO: Radial gradients <3
128126 if ( type === "radial-gradient" ) {
@@ -138,6 +136,6 @@ const generateGradient = (gradient, sizes) => {
138136 ...getVectorsByOrientation ( orientation )
139137 } ;
140138 } ) ;
141- } ;
139+ } ) ;
142140
143141export default generateGradient ;
0 commit comments