From 5bd06895e940e550256165ede438add400d34b3c Mon Sep 17 00:00:00 2001 From: Niklas von Hertzen Date: Thu, 10 Aug 2017 23:25:50 +0800 Subject: [PATCH] Begin implementing webkit-gradient parsing --- src/Gradient.js | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Gradient.js b/src/Gradient.js index 08b52a5..b15c568 100644 --- a/src/Gradient.js +++ b/src/Gradient.js @@ -8,7 +8,9 @@ import Color from './Color'; import Length, {LENGTH_TYPE} from './Length'; const SIDE_OR_CORNER = /^(to )?(left|top|right|bottom)( (left|top|right|bottom))?$/i; +const PERCENTAGE_ANGLES = /^([+-]?\d*\.?\d+)% ([+-]?\d*\.?\d+)%$/i; const ENDS_WITH_LENGTH = /(px)|%|( 0)$/i; +const FROM_TO = /^(from|to)\((.+)\)$/i; export type Direction = { x0: number, @@ -33,18 +35,32 @@ export const parseGradient = ( ): ?Gradient => { if (method === 'linear-gradient') { return parseLinearGradient(args, bounds); + } else if (method === 'gradient' && args[0] === 'linear') { + // TODO handle correct angle + return parseLinearGradient( + ['to bottom'].concat( + args + .slice(3) + .map(color => color.match(FROM_TO)) + .filter(v => v !== null) + // $FlowFixMe + .map(v => v[2]) + ), + bounds + ); } - - // TODO: webkit-gradient syntax }; const parseLinearGradient = (args: Array, bounds: Bounds): Gradient => { const angle = parseAngle(args[0]); - const HAS_DIRECTION = SIDE_OR_CORNER.test(args[0]) || angle !== null; + const HAS_SIDE_OR_CORNER = SIDE_OR_CORNER.test(args[0]); + const HAS_DIRECTION = HAS_SIDE_OR_CORNER || angle !== null || PERCENTAGE_ANGLES.test(args[0]); const direction = HAS_DIRECTION ? angle !== null ? calculateGradientDirection(angle, bounds) - : parseSideOrCorner(args[0], bounds) + : HAS_SIDE_OR_CORNER + ? parseSideOrCorner(args[0], bounds) + : parsePercentageAngle(args[0], bounds) : calculateGradientDirection(Math.PI, bounds); const colorStops = []; const firstColorStopIndex = HAS_DIRECTION ? 1 : 0; @@ -166,3 +182,10 @@ const parseSideOrCorner = (side: string, bounds: Bounds): Direction => { return calculateGradientDirection(Math.PI, bounds); } }; + +const parsePercentageAngle = (angle: string, bounds: Bounds): Direction => { + const [left, top] = angle.split(' ').map(parseFloat); + const ratio = left / 100 * bounds.width / (top / 100 * bounds.height); + + return calculateGradientDirection(Math.atan(isNaN(ratio) ? 1 : ratio) + Math.PI / 2, bounds); +};