1import * as React from 'react'; 2import { View } from 'react-native'; 3import { normalizeColor } from './normalizeColor'; 4export default function NativeLinearGradient({ colors, locations, startPoint, endPoint, ...props }) { 5 const [{ height, width }, setLayout] = React.useState({ 6 height: 1, 7 width: 1, 8 }); 9 // TODO(Bacon): In the future we could consider adding `backgroundRepeat: "no-repeat"`. For more 10 // browser support. 11 const linearGradientBackgroundImage = React.useMemo(() => { 12 return getLinearGradientBackgroundImage(colors, locations, startPoint, endPoint, width, height); 13 }, [colors, locations, startPoint, endPoint, width, height]); 14 return (React.createElement(View, { ...props, style: [ 15 props.style, 16 // @ts-ignore: [ts] Property 'backgroundImage' does not exist on type 'ViewStyle'. 17 { backgroundImage: linearGradientBackgroundImage }, 18 ], onLayout: (event) => { 19 const { width, height } = event.nativeEvent.layout; 20 setLayout((oldLayout) => { 21 // don't set new layout state unless the layout has actually changed 22 if (width !== oldLayout.width || height !== oldLayout.height) { 23 return { height, width }; 24 } 25 return oldLayout; 26 }); 27 if (props.onLayout) { 28 props.onLayout(event); 29 } 30 } })); 31} 32/** 33 * Extracted to a separate function in order to be able to test logic independently. 34 */ 35export function getLinearGradientBackgroundImage(colors, locations, startPoint, endPoint, width = 1, height = 1) { 36 const gradientColors = calculateGradientColors(colors, locations); 37 const angle = calculatePseudoAngle(width, height, startPoint, endPoint); 38 return `linear-gradient(${angle}deg, ${gradientColors.join(', ')})`; 39} 40function calculatePseudoAngle(width, height, startPoint, endPoint) { 41 const getControlPoints = () => { 42 let correctedStartPoint = [0, 0]; 43 if (Array.isArray(startPoint)) { 44 correctedStartPoint = [ 45 startPoint[0] != null ? startPoint[0] : 0.0, 46 startPoint[1] != null ? startPoint[1] : 0.0, 47 ]; 48 } 49 let correctedEndPoint = [0.0, 1.0]; 50 if (Array.isArray(endPoint)) { 51 correctedEndPoint = [ 52 endPoint[0] != null ? endPoint[0] : 0.0, 53 endPoint[1] != null ? endPoint[1] : 1.0, 54 ]; 55 } 56 return [correctedStartPoint, correctedEndPoint]; 57 }; 58 const [start, end] = getControlPoints(); 59 start[0] *= width; 60 end[0] *= width; 61 start[1] *= height; 62 end[1] *= height; 63 const py = end[1] - start[1]; 64 const px = end[0] - start[0]; 65 return 90 + (Math.atan2(py, px) * 180) / Math.PI; 66} 67function calculateGradientColors(colors, locations) { 68 return colors.map((color, index) => { 69 const output = normalizeColor(color); 70 if (locations && locations[index]) { 71 const location = Math.max(0, Math.min(1, locations[index])); 72 // Convert 0...1 to 0...100 73 const percentage = location * 100; 74 return `${output} ${percentage}%`; 75 } 76 return output; 77 }); 78} 79//# sourceMappingURL=NativeLinearGradient.web.js.map