/ / Java: transição de cores suaves - java, animação, cores, transições

Java: transição de cores suaves - java, animação, cores, transições

Estou tentando fazer uma health bare, como pode ser original, começará verde e, depois de perder a saúde, você perceberá que ficará amarelo, depois laranja e depois vermelho .. ou algo relacionado a isso.

Eu tentei usar o método fornecido neste link: https://stackoverflow.com/questions/19841477/java-smooth-color-transition

O resultado desse link foi esse código, apenas um teste do valor 100 a 0, mas terminou em um IllegalArgumentException normalmente Red e Green, e acho que está acima do valor de 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));

Realmente não funcionou, e eu não tenho absolutamente nenhuma idéia de como conseguir transition do jeito que eu desejo.

Então, dentro do meu HealthBar aula, eu tenho um update() método

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

Este código faz uma transição básica em determinados pontos.

Eu preciso criar campos para usar certos colors em certo values do health bar, então agora eu tenho isso ..

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

Vou apenas usar um exemplo para o último bit.

Então eu sei que vou ter um color que eu vou, e um color isso é uma base. Não tenho tanta certeza se preciso de um color para atual. O problema que vejo agora é sobre as etapas da transição porque cada transição tem uma quantidade diferente de etapas.

Resumo e pergunta
Não sei como alcançar o que estou tentando, tudo o que sei com certeza é que preciso de uma base e color, e forneci um link para uma resposta que vi, mas não consegui entender direito. Com as informações fornecidas, como eu consegui transition colors ?

Respostas:

11 para resposta № 1

Passei muito tempo tentando encontrar / criar um algoritmo de mesclagem que funcionou para mim; isso é basicamente o que eu consegui manobrar juntos.

Eu usei essa abordagem para gerar uma transição de gradiente misturando várias cores, como demonstrado Aqui

Basicamente, essa abordagem permite configurar uma série de cores e marcas de porcentagem, para que você obtenha um controle muito maior sobre quais pontos a transição de cores ocorre.

Mistura

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

5 para resposta № 2

ESTÁ BEM, antes Mad postou sua resposta (e 1+ para ela), eu estava trabalhando nisso também, então é melhor postar o que descobri ....

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;
import javax.swing.event.*;

@SuppressWarnings("serial")
public class ColorTransition extends JPanel {

private static final int TRANSITION_DELAY = 30;
private static final int PREF_W = 800;
private static final int PREF_H = 600;
private RgbSliderPanel rgbSliderPanel1 = new RgbSliderPanel("Color 1");
private RgbSliderPanel rgbSliderPanel2 = new RgbSliderPanel("Color 2");
private Color background1;
private Color background2;
private JButton button = new JButton(new ButtonAction("Push Me"));

public ColorTransition() {
setBackground(Color.black);

add(rgbSliderPanel1.getMainPanel());
add(rgbSliderPanel2.getMainPanel());

add(button);

rgbSliderPanel1.addPropertyChangeListener(new PropertyChangeListener() {

@Override
public void propertyChange(PropertyChangeEvent evt) {
if (RgbSliderPanel.COLOR.equals(evt.getPropertyName())) {
setBackground(rgbSliderPanel1.calculateColor());
}
}
});
}

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

@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
button.setEnabled(enabled);
rgbSliderPanel1.setEnabled(enabled);
rgbSliderPanel2.setEnabled(enabled);
}

private class ButtonAction extends AbstractAction {

public ButtonAction(String name) {
super(name);
}

@Override
public void actionPerformed(ActionEvent e) {
ColorTransition.this.setEnabled(false);
background1 = rgbSliderPanel1.calculateColor();
background2 = rgbSliderPanel2.calculateColor();

setBackground(background1);

Timer timer = new Timer(TRANSITION_DELAY, new TransitionListener());
timer.start();
}

private class TransitionListener implements ActionListener {
private int index = 0;

@Override
public void actionPerformed(ActionEvent e) {
if (index > 100) {
((Timer) e.getSource()).stop();
ColorTransition.this.setEnabled(true);
} else {
int r = (int) (background2.getRed() * index / 100.0 + background1
.getRed() * (100 - index) / 100.0);
int g = (int) (background2.getGreen() * index / 100.0 + background1
.getGreen() * (100 - index) / 100.0);
int b = (int) (background2.getBlue() * index / 100.0 + background1
.getBlue() * (100 - index) / 100.0);
setBackground(new Color(r, g, b));
}
index++;
}
}
}

private static void createAndShowGui() {
JFrame frame = new JFrame("ColorTransition");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ColorTransition());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

enum Rgb {
RED("Red"), GREEN("Green"), BLUE("Blue");
private String name;

private Rgb(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

class RgbSliderPanel {
public static final String COLOR = "color";
private JPanel mainPanel = new JPanel();
private SwingPropertyChangeSupport propertyChangeSupport = new SwingPropertyChangeSupport(
this);
private Map<Rgb, JSlider> colorSliderMap = new EnumMap<>(Rgb.class);
private String name;
protected Color color;

public RgbSliderPanel(String name) {
this.name = name;
mainPanel.setBorder(BorderFactory.createTitledBorder(name));
//mainPanel.setOpaque(false);
mainPanel.setLayout(new GridLayout(0, 1));
for (Rgb rgb : Rgb.values()) {
JSlider colorSlider = new JSlider(0, 255, 0);
colorSliderMap.put(rgb, colorSlider);
mainPanel.add(colorSlider);
colorSlider.setBorder(BorderFactory.createTitledBorder(rgb.getName()));
colorSlider.setPaintTicks(true);
colorSlider.setPaintTrack(true);
colorSlider.setMajorTickSpacing(50);
colorSlider.setMinorTickSpacing(10);
colorSlider.addChangeListener(new ChangeListener() {

@Override
public void stateChanged(ChangeEvent e) {
Color oldValue = color;
Color newValue = calculateColor();
color = newValue;
propertyChangeSupport.firePropertyChange(COLOR, oldValue,
newValue);
}
});

}
}

public JComponent getMainPanel() {
return mainPanel;
}

public void setEnabled(boolean enabled) {
for (JSlider slider : colorSliderMap.values()) {
slider.setEnabled(enabled);
}
}

public Color calculateColor() {
int r = colorSliderMap.get(Rgb.RED).getValue();
int g = colorSliderMap.get(Rgb.GREEN).getValue();
int b = colorSliderMap.get(Rgb.BLUE).getValue();
return new Color(r, g, b);
}

public String getName() {
return name;
}

public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}

public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
}