Java:平滑的颜色过渡 [英] Java: Smooth Color Transition

查看:32
本文介绍了Java:平滑的颜色过渡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个健康条,并且可能是原始的,它会从绿色开始,在失去健康后你会发现它会变成黄色,然后是橙色,然后是红色.. 或与之相关的东西.

I am trying to make a health bar, and as what might be original, it will start out green, and after losing health you find that it will turn yellow, then orange, then red.. or something relative to that.

我尝试使用此链接中提供的方法:https://stackoverflow.com/questions/19841477/java-smooth-color-transition

I tried using the method provided in this link: https://stackoverflow.com/questions/19841477/java-smooth-color-transition

该链接的结果是这段代码,只是一个从值 100 到 0 的测试,但它以 IllegalArgumentException 结束,通常为 RedGreen,我猜测的原因是它超过了 255 的值.

The result from that link was this code, just a test from value 100 to 0, but it ended in an IllegalArgumentException at normally Red and Green, and my guess for reason is it being over the value of 255.

Color to = Color.red;
Color base = Color.green;
int red = (int)Math.abs((100 * to.getRed()) + ((1 - 100) * base.getRed()));
int green = (int)Math.abs((100 * to.getGreen()) + ((1 - 100) * base.getGreen()));
int blue = (int)Math.abs((100 * to.getBlue()) + ((1 - 100) * base.getBlue()));
setForeground(new Color(red, green, blue));

它并没有真正奏效,我完全不知道如何让它以我希望的方式transition.

It didn't really work, and I have absolutely no idea how I can get it to transition the way I wish it to.

所以在我的 HealthBar 类中,我有一个 update() 方法

So within my HealthBar class, I have an update() method

public void update() {
    if (getValue() < 10) setForeground(Color.red);
    else if (getValue() < 25) setForeground(Color.orange);
    else if (getValue() < 60) setForeground(Color.yellow);
    else setForeground(Color.green);
}

此代码在某些点执行基本转换.

This code does a basic transition at certain points.

我需要创建字段以在 health bar 的某些 values 处使用某些 colors,所以现在我有了这个..

I need to create fields to use certain colors at certain values of the health bar, so now I have this..

if (getValue() < 10) {
    Color to = Color.black;
    // Color current = getForeground() ?
    Color from = Color.red;
    // ?
}

最后一点我只用一个例子.

I am just going to use an example for the last bit.

所以我知道我将有一个 color 和一个 color 作为基础.我不太确定当前是否需要 color.我现在看到的问题是过渡的步骤,因为每个过渡都有不同数量的步骤.

So I know that I am going to have a color that I am going to, and a color that is a base. I am not so sure if I need a color for current. The problem that I see now is for the steps of the transition because each transition has a different amount of steps.

总结和问题
我不知道如何实现我正在尝试的东西,我所知道的只是我需要一个 to 和 base color,我提供了一个我看到的答案的链接,但我不能'真的想通了.根据给出的信息,我怎么能把它变成 transition colors?

Summary and Question
I don't know how to achieve what I am attempting, all I know for sure is I need a to and base color, and I provided a link to an answer that I saw, but I couldn't really figure it out. With the information given, how could I get it to transition colors ?

推荐答案

我花了很多时间试图找到/创建一个对我有用的混合算法,这基本上是我能够凑到一起的.

I spent a lot of time trying to find/create a blending algorithm that worked for me, this is basically what I was able to hobble together.

我已使用此方法生成混合多种颜色的渐变过渡,如此处所示

I've used this approach to generate a gradient transition mixing multiple colors, as demonstrated here

基本上,这种方法允许您设置一系列颜色和百分比标记,以便您更好地控制颜色在哪些点之间过渡.

Basically, this approach allows you to set up a series of colors and percentage marks so that you gain much greater control over which points the colors transition between.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.text.NumberFormat;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class ColorFading {

    public static void main(String[] args) {
        new ColorFading();
    }

    public ColorFading() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new FadePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class FadePane extends JPanel {

        private final float[] fractions = new float[]{0f, 0.5f, 1f};
        private final Color[] colors = new Color[]{Color.RED, Color.YELLOW, Color.GREEN};
        private float progress = 1f;
        private JSlider slider;

        public FadePane() {
            slider = new JSlider(0, 100);
            setLayout(new BorderLayout());
            add(slider, BorderLayout.SOUTH);

            slider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    progress = ((float)slider.getValue() / 100f);
                    repaint();
                }
            });
            slider.setValue(100);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @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 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;
    }
}

这篇关于Java:平滑的颜色过渡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆