Search code examples
javascripthtmlradial-gradients

How do the createRadialGradient() and addColorStop() methods work?


Can anybody explain me, preferably with illustrative pictures, how do these methods work? I've looked at different examples and tutorials but can't seem to grasp the idea. I understand, that the createRadialGradient() creates two circles, but how do those two circles relate to each other and the addColorStop() method ?


Solution

  • Yes, I know this is necro'd... but it seems a valid question that was never snawered, so I leave this here in case someone else needs it.

    ================================================================================

    Well, a gradient is a smooth shift from one color to another.

    In any gradient, you pick a point where the colors begin, a point where the color ends, and the colors you want, and the color smoothly transitions between them.

    The color stops are there to determine what colors will be a part of the gradient, and where in the gradient those colors will appear.

    In a linear gradient, the color transitions from one color to the next in a straight line so that bands of color form along the line, perpendicular to the axis.

    In a radial gradient, the color wraps itself around a central circle (or point, which is simply a very small circle) and transitions from that center to the edge of the gradient.

    This means that the color bands that make up the gradient form into larger and larger circles as they transition from center to edge.

    HEREis an example of a simple radial gradient transitioning from white in the center to black at the outside edge.

    This is the origin of the syntax for createRadialGradient.

    This first circle will be where the color begins, we will arbitrarily state that it starts in the center... lets say that is x:100,y:100

    The second circle will be where the color ends, since we picked the center to start it, the color finishes at the outside edge of the circle (although these could just as easily be reversed).

    For simplicity's sake, the center point (in this case) will remain the same: x:100,y:100

    The real difference between these circles will be the radius. Since the center should be small, we will give it a radius of 1, while the larger outside radius of the circle, we will make 100.

    This gives us the required parameters:

    x = 100;
    y = 100;
    radiusStart = 1;
    radiusEnd = 100;
    
    var grad = ctx.createRadialGradient(x,y,radiusStart,x,y,radiusEnd);
    

    However, if we try to display this code as is, we won't see anything... this is because we need the color stops.

    Color stops are declared with two parameters... the position and the color of the stop.

    The position is a number between 0 and 1, and represents the percentage of the distance from start to end.

    If we want the color to start at white, then we would use:

    grad.addColorStop(0,'#FFFFFF');
    

    This means that we the color stop starts at 0% of the way down the line (meaning right where the gradient begins), and gives the color to paint there as white.

    Similarly, the second gradient should be black, and should be placed at the very end of the gradient:

    grad.addColorStop(1,'#000000');
    

    Notice that these do not reference context directly... we referenced context to create the gradient, but we are adding stops directly to the gradient that we created.

    When we are finished creating the gradient, then we can use this gradient as a fillStyle (or even a strokeStyle) for as long as the gradient that we created remains in scope.

    Full code:

    x = 100;
    y = 100;
    radiusStart = 1;
    radiusEnd = 100;
    
    var grad = ctx.createRadialGradient(x,y,radiusStart,x,y,radiusEnd);
    grad.addColorStop(0,'#FFFFFF');
    grad.addColorStop(1,'#000000');
    
    ctx.beginPath();
    ctx.arc(x,y,radiusEnd,0,Math.PI*2,false);
    ctx.fillStyle = grad;
    ctx.fill();
    

    While you are playing with this, don't forget to experiment a bit.

    Try adding more than two color stops... this means that instead of transitioning from black to white (boring), you can transition from blue to green to yellow to orange to red to purple.

    Just remember to set the positions appropriately... if you have 6 colors, for example (as above), and you want them evenly spaced, then you would set the positions at .2 intervals:

    grad.addColorStop(0,'#0000FF');
    grad.addColorStop(.2,'#00FF00');
    grad.addColorStop(.4,'#FFFF00');
    grad.addColorStop(.6,'#FF8800');
    grad.addColorStop(.8,'#FF0000');
    grad.addColorStop(1,'#AA00AA');
    

    Any color stops you try to place in the same position will overwrite one another.

    Another cool effect is to set two different centers for the circles when creating the gradient... this lends a different effect to the gradient, and can be a worthy addition to your arsenal.

    HERE are two images from the W3C specification (which itself is HERE). Both of these are radial gradient with different center points for the first and second circles.

    A better example is HERE, although the code itself is written in svg for html backgrounds, the examples still show some great ways to use radial gradients with differing centers. He covers the theory of radial gradients as well as shows some very nice examples.

    Finally, a tip... while it is quite possible to write gradients by hand, its kind of a pain in the butt. It is usually far easier to grab Photoshop, Illustrator, GIMP, or Inkscape, and build the gradient in one of those... then you can adjust the gradient directly until you like it. Then simply copy the color stop information over to your canvas code.

    Hope some of that helps someone.