Animated Background Gradient

Hi all,

I have been seeing this in use on a number of websites, and was wondering if anybody had any ideas how to create an effect like this in Lua. 

Basically, it would be a background gradient that would fade into different colors, creating a nice atmosphere.

Here it is on a website, it seems pretty simple with JavaScript, and I assume it would be replicable in the Corona SDK, but I just do not know how.

Here’s a visual example of what I am looking for:

http://codepen.io/quasimondo/pen/lDdrF
 

If anybody has any thoughts on this that would be great.

Thanks!

Brainstorming on this, you could have two rects with your two separate colors, overlapping one on the other, set a linearWipe fill to the top rect, and transition it back and forth? 

I haven’t tested this suggestion at all, but I can’t think of a reason it won’t work.

I tried two side-by-side rectangles with complementary gradients, then animated the gradients with a timer. Seemed to do fine. The gradient adjustments have to be small and frequent to appear smooth rather than jerky, of course. And the color “distance” can’t be large or you’ll start to get a banding effect.  Here’s a really ugly proof of concept, in which the code is just awful and I didn’t try to animate any but the left-hand-side color, which means it produces the banding I mentioned.

local function GradBump(rec, gradient) gradient.color1[1] = gradient.color1[1] - .01 gradient.color1[2] = gradient.color1[2] - .01 gradient.color1[3] = gradient.color1[3] - .01 rec:setFillColor(gradient) end local gradientLeft = { type="gradient", color1={ .7, .2, .7 }, color2={ .5, .3, .7 }, direction="right" } local gradientRight = { type="gradient", color1={ .5, .3, .7 }, color2={ .4,.4,.7 }, direction="right" } local rec1 = display.newRect(100, 100, 50, 100, 8); rec1:setFillColor(gradientLeft) local rec2 = display.newRect(150, 100, 50, 100, 8); rec2:setFillColor(gradientRight) timer.performWithDelay(300, function () GradBump(rec1, gradientLeft) end, 100)

I am procrastinating so I threw something together as well:

local timeLmt = 3400 centerX = display.contentCenterX centerY = display.contentCenterY local function pulseObj(obj,increm) if increm == -1 then transition.to(obj,{time=timeLmt,x=display.screenOriginX-1100}) else transition.to(obj,{time=timeLmt,x=centerX+80}) end print("transitioning object here") end local rectGradient = {} local colorGradient = { {62/255,35/255,1}, {1,1,60/255}, {1,35/255,98/255}, {45/255,175/255,230/255}, {.5,0,1}, {1,128/255,0} } local inc = #colorGradient local increm = -1 local rectBack = display.newRect(centerX, centerY, display.contentWidth\*2, display.contentHeight) rectBack:setFillColor(0,0,1) for i=1, #colorGradient do rectGradient[i] = display.newRect(centerX, centerY, display.contentWidth\*1.5, display.contentHeight) rectGradient[i]:setFillColor(unpack(colorGradient[i])) --rectGradient[i].x = display.screenOriginX+(i\*(rectGradient[i].width/2)) rectGradient[i].x = centerX+(display.contentWidth/8) rectGradient[i].increm = -1 rectGradient[i].alpha = .9 rectGradient[i].fill.effect = "filter.linearWipe" rectGradient[i].fill.effect.direction = { 1, 0 } rectGradient[i].fill.effect.smoothness = .9 rectGradient[i].fill.effect.progress = 0.5 end local function transitionBackg() timer.performWithDelay(timeLmt/2, function() pulseObj(rectGradient[inc],increm) if inc \> #colorGradient then increm = -1 elseif inc \< 3 then increm = 1 end inc = inc+increm print("inc = "..inc) print("increm = "..increm) end, 0) end transitionBackg()

Thank you both so much!  They both work flawlessly.

Just a question, what variable should I change to make the gradient go from the top to the bottom?

Thanks!

In my example, you’re going to want to change the transition coordinates in the pulseObj() function, and play around with the *.effect values for the rectGradient objects.

In my example where I’m just setting a gradient for the fill, you would need to rearrange the position of the rectangles so they are top/bottom instead of left/right, and then change the direction=“right” to direction=“up” in the gradient tables.

Thank you both so much! I got it working flawlessly, and combined both your solutions to fit my needs :slight_smile:

I really appreciate the help.

Also, if you’re looking for something a bit more complex, you can do some experimenting in the custom shader playground, and create your own custom gradient background.

https://coronalabs.com/blog/2015/04/15/custom-shader-effects/ 

Brainstorming on this, you could have two rects with your two separate colors, overlapping one on the other, set a linearWipe fill to the top rect, and transition it back and forth? 

I haven’t tested this suggestion at all, but I can’t think of a reason it won’t work.

I tried two side-by-side rectangles with complementary gradients, then animated the gradients with a timer. Seemed to do fine. The gradient adjustments have to be small and frequent to appear smooth rather than jerky, of course. And the color “distance” can’t be large or you’ll start to get a banding effect.  Here’s a really ugly proof of concept, in which the code is just awful and I didn’t try to animate any but the left-hand-side color, which means it produces the banding I mentioned.

local function GradBump(rec, gradient) gradient.color1[1] = gradient.color1[1] - .01 gradient.color1[2] = gradient.color1[2] - .01 gradient.color1[3] = gradient.color1[3] - .01 rec:setFillColor(gradient) end local gradientLeft = { type="gradient", color1={ .7, .2, .7 }, color2={ .5, .3, .7 }, direction="right" } local gradientRight = { type="gradient", color1={ .5, .3, .7 }, color2={ .4,.4,.7 }, direction="right" } local rec1 = display.newRect(100, 100, 50, 100, 8); rec1:setFillColor(gradientLeft) local rec2 = display.newRect(150, 100, 50, 100, 8); rec2:setFillColor(gradientRight) timer.performWithDelay(300, function () GradBump(rec1, gradientLeft) end, 100)

I am procrastinating so I threw something together as well:

local timeLmt = 3400 centerX = display.contentCenterX centerY = display.contentCenterY local function pulseObj(obj,increm) if increm == -1 then transition.to(obj,{time=timeLmt,x=display.screenOriginX-1100}) else transition.to(obj,{time=timeLmt,x=centerX+80}) end print("transitioning object here") end local rectGradient = {} local colorGradient = { {62/255,35/255,1}, {1,1,60/255}, {1,35/255,98/255}, {45/255,175/255,230/255}, {.5,0,1}, {1,128/255,0} } local inc = #colorGradient local increm = -1 local rectBack = display.newRect(centerX, centerY, display.contentWidth\*2, display.contentHeight) rectBack:setFillColor(0,0,1) for i=1, #colorGradient do rectGradient[i] = display.newRect(centerX, centerY, display.contentWidth\*1.5, display.contentHeight) rectGradient[i]:setFillColor(unpack(colorGradient[i])) --rectGradient[i].x = display.screenOriginX+(i\*(rectGradient[i].width/2)) rectGradient[i].x = centerX+(display.contentWidth/8) rectGradient[i].increm = -1 rectGradient[i].alpha = .9 rectGradient[i].fill.effect = "filter.linearWipe" rectGradient[i].fill.effect.direction = { 1, 0 } rectGradient[i].fill.effect.smoothness = .9 rectGradient[i].fill.effect.progress = 0.5 end local function transitionBackg() timer.performWithDelay(timeLmt/2, function() pulseObj(rectGradient[inc],increm) if inc \> #colorGradient then increm = -1 elseif inc \< 3 then increm = 1 end inc = inc+increm print("inc = "..inc) print("increm = "..increm) end, 0) end transitionBackg()

Thank you both so much!  They both work flawlessly.

Just a question, what variable should I change to make the gradient go from the top to the bottom?

Thanks!

In my example, you’re going to want to change the transition coordinates in the pulseObj() function, and play around with the *.effect values for the rectGradient objects.

In my example where I’m just setting a gradient for the fill, you would need to rearrange the position of the rectangles so they are top/bottom instead of left/right, and then change the direction=“right” to direction=“up” in the gradient tables.

Thank you both so much! I got it working flawlessly, and combined both your solutions to fit my needs :slight_smile:

I really appreciate the help.

Also, if you’re looking for something a bit more complex, you can do some experimenting in the custom shader playground, and create your own custom gradient background.

https://coronalabs.com/blog/2015/04/15/custom-shader-effects/