Gradient Paint Burst
Hi, Im trying to accomplish either of the following two effects.
- Have a circle with a gradient paint that fades from the outside in
equally all around (not just a left/right top/down wash)
or preferably
- Have a rectangle with the same effect where the sides are fading to
white as it reaches the center of the screen
I checked the Java2D demo in the SDK and it didnt have an example of this. I googled around without finding an example of this.
Here is my very straight-forward code.
What can i do to get the effect I am looking for?
As you can see, this code only has the fill fade from the top and bottom to the center but not all around from the sides.
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
publicclass GradientBurstextends JPanel{
publicstaticvoid main(String[] args){
new GradientBurst();
}
public GradientBurst(){
this.setBackground(Color.BLACK);
display();
}
publicvoid display(){
frame.setContentPane(this);
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
publicvoid paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D gfx = (Graphics2D)g;
Color startColor = Color.WHITE;
Color endColor = Color.GRAY;
Point pt1 =new Point(250, 250);
Point pt2 =new Point(250, 0);
GradientPaint gradientPaint =
new GradientPaint(pt1, startColor, pt2, endColor,true);
gfx.setPaint(gradientPaint);
gfx.fill(new Ellipse2D.Double(0, 0, 500, 500));
}
JFrame frame =new JFrame("Gradient Burst");
}
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class RectGradient extends JPanel
{
BufferedImage image;
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
int w = getWidth();
int h = getHeight();
Rectangle r = new Rectangle(w/16, h/16, w*13/32, h*7/8);
double radius = Point2D.distance(r.x, r.y, r.getCenterX(), r.getCenterY());
RoundGradientPaint rgp = new RoundGradientPaint(r.getCenterX(), r.getCenterY(),
Color.white,
new Point2D.Double(0,radius),
Color.blue);
g2.setPaint(rgp);
g2.fill(r);
if(image == null)
makeImage(w*13/32, h*7/8, Color.white, Color.blue);
int x = w*17/32;
int y = h/16;
g2.drawImage(image, x, y, this);
}
private void makeImage(int w, int h, Color center, Color bg)
{
int[] data = new int[w*h];
Rectangle r = new Rectangle(w, h);
int index = 0;
for(int row = 0; row < h; row++)
{
for(int col = 0; col < w; col++)
{
double dy = row - h/2.0;
double dx = col - w/2.0;
double theta = Math.atan2(dy, dx);
Point2D.Double bp = getBoundryPoint(theta, r);
double toEdge = bp.distance(w/2.0, h/2.0);
double toPoint = Point2D.distance(w/2.0, h/2.0, col, row);
double ratio = toPoint/toEdge;
if(ratio > 1.0) ratio = 1.0;
int red= (int)(center.getRed() +
ratio*(bg.getRed()- center.getRed()));
int green = (int)(center.getGreen() +
ratio*(bg.getGreen() - center.getGreen()));
int blue = (int)(center.getBlue() +
ratio*(bg.getBlue() - center.getBlue()));
data[index++] = (red << 16) | (green << 8) | blue;
}
}
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
image.setRGB(0, 0, w, h, data, 0, w);
}
private Point2D.Double getBoundryPoint(double theta, Rectangle r)
{
double cx = r.getCenterX();
double cy = r.getCenterY();
double W = r.getWidth()/2;
double H = r.getHeight()/2;
double R = Point2D.distance(cx, cy, cx+W, cy+H);
double x = cx + R * Math.cos(theta);
double y = cy + R * Math.sin(theta);
Point2D.Double p = new Point2D.Double();
int outcode = r.outcode(x, y);
switch(outcode)
{
case Rectangle2D.OUT_TOP:
p.x = cx - H * ((x - cx)/(y - cy));
p.y = cy - H;
break;
case Rectangle2D.OUT_LEFT:
p.x = cx - W;
p.y = cy - W * ((y - cy)/(x - cx));
break;
case Rectangle2D.OUT_BOTTOM:
p.x = cx + H * ((x - cx)/(y - cy));
p.y = cy + H;
break;
case Rectangle2D.OUT_RIGHT:
p.x = cx + W;
p.y = cy + W * ((y - cy)/(x - cx));
break;
default:
System.out.printf("non-cardinal outcode: %d%n", outcode);
}
return p;
}
private ComponentListener resizer = new ComponentAdapter()
{
public void componentResized(ComponentEvent e)
{
image = null;
repaint();
}
};
public static void main(String[] args)
{
RectGradient test = new RectGradient();
test.addComponentListener(test.resizer);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(test);
f.setSize(500,275);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
74philip,
Thank you very much. I actually came to the same solution myself.
I didnt know about outcode though... THATS A GREAT METHOD!
I was doing the math out myself.
One thing i did differently in my solution was to skew the ratio
so that it is brighter longer in the center.
I just used a square but i suppose other functions might look nicer.
I got the same weird "white X" effect on my rect gradient which i
first thought was an error but since you get the same effect i
suppose its a result of the math.
Thanks again.
double toEdge = bp.distance(w/2.0, h/2.0);
double toPoint = Point2D.distance(w/2.0, h/2.0, col, row);
double ratio = toPoint/toEdge;
if(ratio > 1.0) ratio = 1.0;
// --> ratio = ratio * ratio;