Pairs are handy for this, because we can prepare a list of percentages and colors and pass that to our method. The left value will contain the percentage, the right value will contain the color. Our gradient will be a simple red-yellow-green gradient:
dim colors(2) as pair
colors(0) = 0.0 : &cFF0000
colors(1) = 0.5 : &cFFFF00
colors(2) = 1.0 : &c00FF00
This basically says that at 0%, it should be red. At 50%, it should be yellow. At 100%, it should be green. We'll pass this array a method which defines the width, height, and direction of the gradient:
Function CreateGradient(Width As Integer, Height As Integer, Points() As Pair, Vertical As Boolean = false) As Picture
dim p as new picture(width,height,32)
dim i,x,w,nextstart as integer
dim pointOne,pointTwo as pair
dim colorOne,colorTwo,blendedColor as color
dim pct as double
for i = 0 to ubound(points) - 1
pointone = points(i)
pointtwo = points(i + 1)
colorone = pointone.right
colortwo = pointtwo.right
if vertical then
w = (pointtwo.left.doublevalue * height) - nextstart
else
w = (pointtwo.left.doublevalue * width) - nextstart
end
for x = 0 to w
pct = x / w
blendedcolor = rgb((colorone.red * (1 - pct)) + (colortwo.red * pct),(colorone.green * (1 - pct)) + (colortwo.green * pct),(colorone.blue * (1 - pct)) + (colortwo.blue * pct))
p.graphics.forecolor = blendedcolor
if vertical then
p.graphics.drawline(-1,x + nextstart,p.width + 1,x + nextstart)
else
p.graphics.drawline(x + nextstart,-1,x + nextstart,p.height + 1)
end
next
nextstart = nextstart + w
next
return p
End Function
And that's all you need to create better gradients on-the-fly. Just for fun, here's the colors you need to draw a gradient similar to Apple Mail's toolbar buttons:
dim colors(3) as pair
colors(0) = 0.00 : &cDADBDD
colors(1) = 0.50 : &cD6D7DA
colors(2) = 0.51 : &cC8CBCE
colors(3) = 1.00 : &cDDE0E3
6 comments:
That sounds really good but what if you needed to draw the gradient at an angle? Or even harder - radial gradients. How might one tackle that?
Thanks much.
Angled gradients are probably the more difficult. You basically need to recall some high school math and draw lines. Radials are simple, draw circles.
How about providing a couple of screenshots of the effect. Nothing large; doesn't even need to be the entire window -- just a snapshot of what the code does.
@Anonymous: It took me four minutes to paste Thom's code into a project and test it.
I've put a very amateurish screenshot at
http://rbjottings.co.uk/picstuff/gradient.png
Ahhhh but your missing the point of a screenshot request -- it's for users who DO NOT HAVE REALbasic installed.
For example, I'm posting this from a BlackBerry.
I've decided to take part of the challenge. Here's the code to create radial gradients:
Function CreateRadialGradient(Width As Integer, Height As Integer, Points() As Pair) As Picture
// Change this constant to modify the quality. The higher the number, the more
// passes will be made to refine the gradient, at the cost of rendering speed.
const quality = 50
dim p as new picture(width,height,32)
dim i,x,y,v,w,h,s,e as integer
dim pointOne,pointTwo as pair
dim colorOne,colorTwo,blendedColor as color
dim pct,amt as double
dim curLeft,curTop,curWidth,curHeight,destLeft,destTop,destWidth,destHeight as integer
p.graphics.forecolor = points(0).right.colorvalue
p.graphics.fillrect(0,0,p.width,p.height)
for i = 0 to ubound(points) - 1
pointone = points(i)
pointtwo = points(i + 1)
colorone = pointone.right
colortwo = pointtwo.right
destwidth = ((1 - pointtwo.left.doublevalue) * width)
destheight = ((1 - pointtwo.left.doublevalue) * height)
destleft = curleft + (destwidth / 2)
desttop = curtop + (destheight / 2)
curwidth = (1 - pointone.left.doublevalue) * width
curheight = (1 - pointone.left.doublevalue) * height
s = pointone.left.doublevalue * quality
e = pointtwo.left.doublevalue * quality
for v = s to e
amt = v / quality
x = amt * (width / 2)
y = amt * (height / 2)
w = width * (1 - (v / quality))
h = height * (1 - (v / quality))
pct = (v - s) / (e - s)
blendedcolor = rgb((colorone.red * (1 - pct)) + (colortwo.red * pct),(colorone.green * (1 - pct)) + (colortwo.green * pct),(colorone.blue * (1 - pct)) + (colortwo.blue * pct))
p.graphics.forecolor = blendedcolor
p.graphics.filloval(x,y,w,h)
next
curleft = curleft + destleft
curtop = curtop + desttop
next
return p
End Function
Not sure how well that code will appear in the comments though.
Post a Comment