我正在尝试创建一个反应原生的渐变,当应用程序打开时将以一种颜色开始,然后每30秒逐渐变为另一种颜色.常规线性渐变无需添加动画即可工作.我尝试使用插值和动画时序,如本机文档中所示,但似乎没有任何作用.
我的代码:
import React, {Component} from 'react'; import {processColor, AppRegistry, StyleSheet, Dimensions, Animated, Image, Easing, View} from 'react-native'; import TimerMixin from 'react-timer-mixin'; import LinearGradient from 'react-native-linear-gradient'; var screenWidth = Dimensions.get('window').width; var screenHeight = Dimensions.get('window').height; //HEX version of colors var gradientColors = [['#EF2A2A', '#EF6A2A'], //Red ['#EF6A2A', '#EFD82A'], //Orange ['#1BD170', '#61E822'], //Green ['#22D2E6', '#26F084'], //Aqua ['#2A3BEF', '#2ADCEF'], //Blue ['#EF2AD2', '#2A3BEF'], //Purple ['#EF2AD2', '#EF2A2A'] //Pink ] var gradientColorsNoHash = [['EF2A2A', 'EF6A2A'], //Red ['EF6A2A', 'EFD82A'], //Orange ['1BD170', '61E822'], //Green ['22D2E6', '26F084'], //Aqua ['2A3BEF', '2ADCEF'], //Blue ['EF2AD2', '2A3BEF'], //Purple ['EF2AD2', 'EF2A2A'] //Pink ] /*var gradientColors = [['ef2a2a', 'ef6a2a'], //Red ['ef6a2a', 'efd82a'], //Orange ['1bd170', '61e822'], //Green ['22d2e6', '26f084'], //Aqua ['2a3bef', '2adcef'], //Blue ['ef2ad2', '2a3bef'], //Purple ['ef2ad2', 'ef2a2a'] //Pink ]*/ //RGBA Version of Colors /*var gradientColors = [['rgba(239, 42, 42, 1)', 'rgba(239, 106, 42, 1)'], //Red ['rgba(239, 106, 42, 1)', 'rgba(239, 216, 42, 1)'], //Orange ['rgba(0, 221, 103, 1)', 'rgba(97, 232, 35, 1)'], //Green ['rgba(34, 210, 230, 1)', 'rgba(38, 240, 132, 1)'], //Aqua ['rgba(42, 59, 239, 1)', 'rgba(42, 220, 239, 1)'], //Blue ['rgba(239, 42, 210, 1)', 'rgba(42, 59, 239, 1)'], //Purple ['rgba(239, 42, 210, 1)', 'rgba(239, 42, 42, 1)'] //Pink ]*/ function hex(c) { var s = "0123456789abcdef"; var i = parseInt(c); if (i == 0 || isNaN(c)) return "00"; i = Math.round(Math.min (Math.max (0, i), 255)); //console.log('hex(c) complete!'); return s.charAt((i - i % 16) / 16) + s.charAt(i % 16); } // Convert an RGB triplet to a hex string function convertToHex (rgb) { return hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]); } // Convert a hex string to an RGB triplet function convertToRGB(hex) { var color = []; color[0] = parseInt(hex.substring(0, 2), 16); color[1] = parseInt(hex.substring(2, 4), 16); color[2] = parseInt(hex.substring(4, 6), 16); return color; } function generateColor(colorStart,colorEnd,colorCount) { // The beginning of your gradient var start = convertToRGB(colorStart); // The end of your gradient var end = convertToRGB(colorEnd); // The number of colors to compute var len = colorCount; //Alpha blending amount var alpha = 0.0; var saida = []; for (i = 0; i < len; i++) { var c = []; alpha += (1.0/len); c[0] = start[0] * alpha + (1 - alpha) * end[0]; c[1] = start[1] * alpha + (1 - alpha) * end[1]; c[2] = start[2] * alpha + (1 - alpha) * end[2]; saida.push(convertToHex(c)); } return saida; } var number = randomIntFromInterval(0,6) function randomIntFromInterval(min,max) { return Math.floor(Math.random()*(max-min+1)+min); } const GradientView = React.createClass({ mixins: [TimerMixin], getInitialState() { return { gradIndex: number, colorTop: gradientColors[number][0], colorBottom: gradientColors[number][1], } }, componentDidMount() { this.setInterval(() => { var count = 0 var topGradArray = generateColor(gradientColorsNoHash[this.state.gradIndex][0],(this.state.gradIndex === 6 ? 0 : gradientColorsNoHash[this.state.gradIndex+1][0] ),770); var bottomGradArray = generateColor(gradientColorsNoHash[this.state.gradIndex][1],(this.state.gradIndex === 6 ? 0 : gradientColorsNoHash[this.state.gradIndex+1][1] ),770); console.log('Gradients Made'); var clearId = this.setInterval(() => { if (count == 0) { this.setState({ clearId: clearId, gradIndex: ( this.state.gradIndex === 6 ? 0 : this.state.gradIndex+1 ) }); console.log('clearId SET!'); } this.setState({ colorTop: processColor(topGradArray[count]), colorBottom: processColor(bottomGradArray[count]), }); count = count+1 if (count == 769) { console.log('colorTop and Bottom Saved'); this.clearInterval(this.state.clearId) } }, 13); }, 30000); }, render(){ return(); } }); const styles = StyleSheet.create({ translucentContainer: { width: screenWidth, height: screenHeight, backgroundColor: 'white', opacity: 0.3, }, }); export default GradientView; AppRegistry.registerComponent('GradientView', () => GradientView);
更新:在经历了许多不同的资源之后,我得出的结论是,使LinearGradient类动画化的唯一方法是像文档中那样逐步和快速地改变颜色.但是,它们的示例是连续的,不允许您设置所需的最终颜色.对于我的应用程序,我希望渐变保持一种颜色30秒,然后经过10秒过渡到下一个颜色渐变,然后重复.例如,它看起来像:红色渐变(30秒),红色转换为橙色(10秒),橙色渐变(30秒),橙色转换为绿色(10秒)等.
我有两种类型的错误,这个代码似乎是替代的.通常,第一个错误是在第一个计时器(30秒计时器)熄灭时出现的错误:
在解除该错误消息以查看将发生的情况后,当同一个计时器再次关闭时会弹出此错误:
在这一点上,我认为错误的来源是在包含的函数中正确生成颜色 componentDidMount()
我找到了有效的解决方案!
使用线性插值生成渐变.这是我发现正确控制渐变的最简单方法.
chroma.js:
我找到了一个名为chroma.js的库,可以做得很好!他们有一个名为scale.colors的方法,可以为你完成这项工作!
安装包:
npm install chroma-js
您可以调整INTERVAL
和GRADIENT_COLOR_LENGTH
常量来更改效果.
然后在代码中使用生成的频谱变量:
import React from 'react' import { AppRegistry, StyleSheet, Dimensions, View } from 'react-native' import TimerMixin from 'react-timer-mixin' import LinearGradient from 'react-native-linear-gradient' import Chroma from 'chroma-js' var screenWidth = Dimensions.get('window').width var screenHeight = Dimensions.get('window').height const TOP_COLORS = ['#EF2A2A', '#EF6A2A', '#1BD170', '#22D2E6', '#2A3BEF', '#EF2AD2', '#EF2AD2'] const BOTTOM_COLORS = ['#EF6A2A', '#EFD82A', '#61E822', '#26F084', '#2ADCEF', '#2A3BEF', '#EF2A2A'] const GRADIENT_COLOR_LENGTH = 700 const TOP_COLORS_SPECTRUM = Chroma.scale(TOP_COLORS).colors(GRADIENT_COLOR_LENGTH) const BOTTOM_COLORS_SPECTRUM = Chroma.scale(BOTTOM_COLORS).colors(GRADIENT_COLOR_LENGTH) const INTERVAL = 50 const GradientView = React.createClass({ mixins: [TimerMixin], getInitialState () { return { topIndex: 0, bottomIndex: 0, colorTop: TOP_COLORS_SPECTRUM[0], colorBottom: BOTTOM_COLORS_SPECTRUM[0] } }, componentDidMount () { this.setInterval(() => { let { topIndex, bottomIndex } = this.state topIndex++ if (topIndex === TOP_COLORS_SPECTRUM.length) { topIndex = 0 } bottomIndex++ if (bottomIndex === BOTTOM_COLORS_SPECTRUM.length) { bottomIndex = 0 } this.setState({ topIndex: topIndex, bottomIndex: bottomIndex, colorTop: TOP_COLORS_SPECTRUM[topIndex], colorBottom: BOTTOM_COLORS_SPECTRUM[bottomIndex] }) }, INTERVAL) }, render () { return () } }) const styles = StyleSheet.create({ translucentContainer: { width: screenWidth, height: screenHeight, backgroundColor: 'white', opacity: 0.3 } }) export default GradientView AppRegistry.registerComponent('GradientView', () => GradientView)