颜色衰落algorithm?

我创build了一些自定义的Swing组件,我想从一种颜色淡入到另一种颜色。 目前,我正在从RGB转换到HSB,然后通过色相值递增,并在绘画前转换回RGB,工作很好。

然而,这循环所有的颜色(即试图从黄色,橙色,红色等从蓝色到绿色的循环渐变)。 是否有一个体面的algorithm/方法直接从一种颜色淡入到另一种颜色?

编辑:我已经有更新通过摆动计时器(我试图避开像瘟疫线程触摸组件)。 感谢您的build议,今天晚上我会去的,谢谢!

基于此示例 ,下面的Queue<Color>Color.green循环到Color.blue ,再以N = 32步骤返回到Color.green 。 请注意, Color.green在数值上小于HSB模型中的Color.blue 。 另请参阅使用HSB的相关示例 。

在这里输入图像描述

 public Flash(JComponent component) { this.component = component; float gHue = Color.RGBtoHSB(0, 1, 0, null)[0]; float bHue = Color.RGBtoHSB(0, 0, 1, null)[0]; for (int i = 0; i < N; i++) { clut.add(Color.getHSBColor(gHue + (i * (bHue - gHue) / N), 1, 1)); } for (int i = 0; i < N; i++) { clut.add(Color.getHSBColor(bHue - (i * (bHue - gHue) / N), 1, 1)); } } 

我使用了多种方法来达到相同的效果。

Baiscally我使用一个相同的API接口作为LinearGradientPaint ,其中我提供了一个分数数组和一个颜色数组,然后基于一个float百分比,我计算出最终的混合颜色。

这使我可以通过相同的algorithm产生许多有效的结果。

在这里输入图像描述

虽然此示例旨在演示各种颜色的混合,但您可以简单地为两种颜色提供两种颜色和一部分{0f, 1f}

这使我可以有效地做彩色animation。

 public class ColorFade { public static void main(String[] args) { new ColorFade(); } public ColorFade() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); // frame.add(new FadePane()); frame.add(new ColorFadePane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class FadePane extends JPanel { private float[] fractions = new float[]{0f, 0.25f, 0.5f, 1f}; private Color[] colors = new Color[]{Color.GREEN, Color.BLUE, Color.YELLOW, Color.RED}; private float direction = 0.05f; private float progress = 0f; public FadePane() { Timer timer = new Timer(125, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (progress + direction > 1f) { direction = -0.05f; } else if (progress + direction < 0f) { direction = 0.05f; } progress += direction; repaint(); } }); timer.setCoalesce(true); timer.setRepeats(true); timer.start(); } @Override public Dimension getPreferredSize() { return new Dimension(100, 100); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); int width = getWidth(); int height = getHeight(); Color startColor = blendColors(fractions, colors, progress); g2d.setColor(startColor); g2d.fillRect(0, 0, width, height); g2d.dispose(); } } public class ColorFadePane extends JPanel { private float[] fractions = new float[]{0f, 0.25f, 0.5f, 1f}; private Color[] colors = new Color[]{Color.GREEN, Color.BLUE, Color.YELLOW, Color.RED}; public ColorFadePane() { } @Override public Dimension getPreferredSize() { return new Dimension(200, 100); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); int width = getWidth(); int height = getHeight(); int bandWidth = width / 100; for (int index = 0; index < 100; index++) { float progress = (float)index / (float)100; Color color = blendColors(fractions, colors, progress); int x = bandWidth * index; int y = 0; g2d.setColor(color); g2d.fillRect(x, y, bandWidth, height); } g2d.dispose(); } } public static Color blendColors(float[] fractions, Color[] colors, float progress) { Color color = null; if (fractions != null) { if (colors != null) { if (fractions.length == colors.length) { int[] indicies = getFractionIndicies(fractions, progress); float[] range = new float[]{fractions[indicies[0]], fractions[indicies[1]]}; Color[] colorRange = new Color[]{colors[indicies[0]], colors[indicies[1]]}; float max = range[1] - range[0]; float value = progress - range[0]; float weight = value / max; color = blend(colorRange[0], colorRange[1], 1f - weight); } else { throw new IllegalArgumentException("Fractions and colours must have equal number of elements"); } } else { throw new IllegalArgumentException("Colours can't be null"); } } else { throw new IllegalArgumentException("Fractions can't be null"); } return color; } public static int[] getFractionIndicies(float[] fractions, float progress) { int[] range = new int[2]; int startPoint = 0; while (startPoint < fractions.length && fractions[startPoint] <= progress) { startPoint++; } if (startPoint >= fractions.length) { startPoint = fractions.length - 1; } range[0] = startPoint - 1; range[1] = startPoint; return range; } public static Color blend(Color color1, Color color2, double ratio) { float r = (float) ratio; float ir = (float) 1.0 - r; float rgb1[] = new float[3]; float rgb2[] = new float[3]; color1.getColorComponents(rgb1); color2.getColorComponents(rgb2); float red = rgb1[0] * r + rgb2[0] * ir; float green = rgb1[1] * r + rgb2[1] * ir; float blue = rgb1[2] * r + rgb2[2] * ir; if (red < 0) { red = 0; } else if (red > 255) { red = 255; } if (green < 0) { green = 0; } else if (green > 255) { green = 255; } if (blue < 0) { blue = 0; } else if (blue > 255) { blue = 255; } Color color = null; try { color = new Color(red, green, blue); } catch (IllegalArgumentException exp) { NumberFormat nf = NumberFormat.getNumberInstance(); System.out.println(nf.format(red) + "; " + nf.format(green) + "; " + nf.format(blue)); exp.printStackTrace(); } return color; } } 

最简单的方法是插入每个RGB值之间。 这对所有语言都是一样的 – python代码如下所示:

 steps = 10 rgb1 = [ 'AA', '08', 'C3' ] rgb2 = [ '03', '88', '1C' ] h1 = map( lambda s: int( '0x'+s, 0 ), rgb1 ) h2 = map( lambda s: int( '0x'+s, 0 ), rgb2 ) inc = [0, 0, 0] for i in range(0,3): inc[i] = ( h2[i] - h1[i] ) / ( steps - 1 ) for i in range(0,steps-1): print '<span style="background: #%02x%02x%02x"> &nbsp; %i &nbsp; </span>' % ( h1[0] + i * inc[0], h1[1] + i * inc[1], h1[2] + i * inc[2], i+1 ) print '<span style="background: #%02x%02x%02x"> &nbsp; %i &nbsp; </span>' % ( h2[0], h2[1], h2[2], steps ) 

提示

  1. 使用摆动计时器慢动作效果
  2. 将RGB值减一个数字,比如x

Tadaaaa .. 🙂

更新:如果你愿意,你可以玩x价值。

使用Math.Random()函数在执行期间为x生成伪随机值

HovercraftFullOfEels&mKorbel,感谢您的意见

你可以线性插值从开始RGB颜色到最后想要的颜色。

这意味着如果你有rgb(255,255,0)作为开始颜色和rgb(50,50,50)作为目标,并且你想要达到最终颜色的5个步骤你改编(-41 = (255-50)/5, -41, 10)在每一步导致以下颜色:

 rgb(255,255, 0) rgb(214,214, 10) rgb(173,173, 20) rgb(132,132, 30) rgb( 91, 91, 40) rgb( 50, 50, 50) 

这就是所谓的线性渐变,很容易实现,但是当然还有各种其他技术可以在颜色之间进行很好的转换。