From 463b072dac1beda0ae89dbda268728b9035296e7 Mon Sep 17 00:00:00 2001 From: Dral Date: Sun, 4 Oct 2015 14:35:48 -0700 Subject: [PATCH] Support hex values in outputRange MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: 1. Should I add an example of this to the UIExplorer Animation example? 2. Should I support mixing hex and rgba values in outputRange? It is possible with this implementation, but may cause confusion Closes https://github.com/facebook/react-native/pull/3177 Reviewed By: @​svcscm Differential Revision: D2506947 Pulled By: @vjeux --- Libraries/Animated/src/Interpolation.js | 15 ++++++ .../src/__tests__/Interpolation-test.js | 53 ++++++++++++++++--- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/Libraries/Animated/src/Interpolation.js b/Libraries/Animated/src/Interpolation.js index fecbf0d4a..99c36834c 100644 --- a/Libraries/Animated/src/Interpolation.js +++ b/Libraries/Animated/src/Interpolation.js @@ -11,6 +11,8 @@ */ 'use strict'; +var tinycolor = require('tinycolor2'); + // TODO(#7644673): fix this hack once github jest actually checks invariants var invariant = function(condition, message) { if (!condition) { @@ -163,6 +165,18 @@ function interpolate( return result; } +function colorToRgba( + input: string +): string { + var color = tinycolor(input); + if (color.isValid()) { + var {r, g, b, a} = color.toRgb(); + return `rgba(${r}, ${g}, ${b}, ${a === undefined ? 1 : a})`; + } else { + return input; + } +} + var stringShapeRegex = /[0-9\.-]+/g; /** @@ -178,6 +192,7 @@ function createInterpolationFromStringOutputRange( ): (input: number) => string { var outputRange: Array = (config.outputRange: any); invariant(outputRange.length >= 2, 'Bad output range'); + outputRange = outputRange.map(colorToRgba); checkPattern(outputRange); // ['rgba(0, 100, 200, 0)', 'rgba(50, 150, 250, 0.5)'] diff --git a/Libraries/Animated/src/__tests__/Interpolation-test.js b/Libraries/Animated/src/__tests__/Interpolation-test.js index aec20ba2b..4dca8ab61 100644 --- a/Libraries/Animated/src/__tests__/Interpolation-test.js +++ b/Libraries/Animated/src/__tests__/Interpolation-test.js @@ -10,7 +10,8 @@ jest .dontMock('Interpolation') - .dontMock('Easing'); + .dontMock('Easing') + .dontMock('tinycolor2'); var Interpolation = require('Interpolation'); var Easing = require('Easing'); @@ -223,6 +224,39 @@ describe('Interpolation', () => { expect(interpolation(1)).toBe('rgba(50, 150, 250, 0.5)'); }); + it('should work with output ranges as short hex string', () => { + var interpolation = Interpolation.create({ + inputRange: [0, 1], + outputRange: ['#024', '#9BF'], + }); + + expect(interpolation(0)).toBe('rgba(0, 34, 68, 1)'); + expect(interpolation(0.5)).toBe('rgba(76.5, 110.5, 161.5, 1)'); + expect(interpolation(1)).toBe('rgba(153, 187, 255, 1)'); + }); + + it('should work with output ranges as long hex string', () => { + var interpolation = Interpolation.create({ + inputRange: [0, 1], + outputRange: ['#FF9500', '#87FC70'], + }); + + expect(interpolation(0)).toBe('rgba(255, 149, 0, 1)'); + expect(interpolation(0.5)).toBe('rgba(195, 200.5, 56, 1)'); + expect(interpolation(1)).toBe('rgba(135, 252, 112, 1)'); + }); + + it('should work with output ranges with mixed hex and rgba strings', () => { + var interpolation = Interpolation.create({ + inputRange: [0, 1], + outputRange: ['rgba(100, 120, 140, .5)', '#87FC70'], + }); + + expect(interpolation(0)).toBe('rgba(100, 120, 140, 0.5)'); + expect(interpolation(0.5)).toBe('rgba(117.5, 186, 126, 0.75)'); + expect(interpolation(1)).toBe('rgba(135, 252, 112, 1)'); + }); + it('should work with negative and decimal values in string ranges', () => { var interpolation = Interpolation.create({ inputRange: [0, 1], @@ -242,12 +276,19 @@ describe('Interpolation', () => { expect(() => { interpolation('45rad'); }).toThrow(); }); - it('should crash when defining output range with different pattern', () => { - expect(() => Interpolation.create({ - inputRange: [0, 1], - outputRange: ['rgba(0, 100, 200, 0)', 'rgb(50, 150, 250)'], - })).toThrow(); + it('should support a mix of color patterns', () => { + var interpolation = Interpolation.create({ + inputRange: [0, 1, 2], + outputRange: ['rgba(0, 100, 200, 0)', 'rgb(50, 150, 250)', 'red'], + }); + expect(interpolation(0)).toBe('rgba(0, 100, 200, 0)'); + expect(interpolation(0.5)).toBe('rgba(25, 125, 225, 0.5)'); + expect(interpolation(1.5)).toBe('rgba(152.5, 75, 125, 1)'); + expect(interpolation(2)).toBe('rgba(255, 0, 0, 1)'); + }); + + it('should crash when defining output range with different pattern', () => { expect(() => Interpolation.create({ inputRange: [0, 1], outputRange: ['20deg', '30rad'],