0

I would like to know how to create a rainbow effect in my canvas in the fill style, like for it to change colors at certain intervals or when I continually press a key. Like from red to blue, etc, similar to how you can add a rainbow effect to text.

<script type="text/javascript">
var GAME_SPEED = 1000/60; //game rate
var x = 100;
var y = 100;
var sideLength = 10;

var leftKey = false;
var rightKey = false;
var upKey = false;
var downKey = false;
var spaceKey = false;

window.onload = function()
 {
  c = document.getElementById("marCanvas2");
  c.width = window.innerWidth*0.9;
  c.height = window.innerHeight*0.9;
  window.setInterval("draw()" , GAME_SPEED);
 }

document.onkeyup = function(event)
{
 switch(event.keyCode)
 {
  case 37: leftKey =false;
  break;
  case 39: rightKey = false;
  break;
  case 38: upKey = false;
  break;
  case 40: downKey = false;
  break;
  case 32: spaceKey = false;
  break;
 }
}

document.onkeydown = function(event)
{
 switch(event.keyCode)
 {
  case 37: leftKey =true;
  break;
  case 39: rightKey = true;
  break;
  case 38: upKey = true;
  break;
  case 40: downKey = true;
  break;
  case 32: spaceKey = true;
  break;
 }
}


function draw()
{
 if(leftKey == true)
{
 x--;
}

if(rightKey == true)
{
 x++;
}

if(upKey == true)
{
 y--;
}

if(downKey == true)
{
 y++;
}

if(spaceKey == true)
{
 sideLength++;
}
 var c = document.getElementById("marCanvas2");
 var cntxt = c.getContext("2d");
 cntxt.fillStyle= " ";
 cntxt.fillRect(x, y, sideLength, sideLength);
}
</script>
</head>
 <body>
 <!--Marlon Jacques -->
<canvas id="marCanvas2" style="border: 5px solid
#000000;">
Your browser does not support the canvas element.
</canvas>
</body>
</html>
jnnkkkn
  • 17
  • 1
  • 6
  • Are you talking about a [linear gradient](http://www.html5canvastutorials.com/tutorials/html5-canvas-linear-gradients/)? – Philipp Mar 12 '15 at 11:10
  • Yea but I want it it to change color every few seconds. – jnnkkkn Mar 12 '15 at 12:03
  • Here's a rainbow script from a previous Stackoverflow question: http://stackoverflow.com/questions/1211705/paint-me-a-rainbow. One of the answerers presents a lib that does rainbows. You can use the lib plus your own keystroke code to clear the canvas and redraw a different set of rainbow colors with each keystroke. Here's a link to their rainbow lib: https://github.com/anomal/RainbowVis-JS – markE Mar 12 '15 at 16:40

1 Answers1

4

You can do this by dynamically defining the start and end of the gradient. What colors you want is up to you, but you can use for example HSL color model to "rotate" through a color range with different speed for start and end.

Example 1

var ctx = document.querySelector("canvas").getContext("2d"),
    angleA = Math.random() * 360,                                // start angle (for HSL)
    angleB = Math.random() * 360,
    stepA = 1.2, stepB = 0.7;                                    // "speed" for change

function createGradient() {
  var gr = ctx.createLinearGradient(0, 0, 500, 0);               // create gradient
  gr.addColorStop(0, "hsl(" + (angleA % 360) + ",100%, 50%)");   // start color
  gr.addColorStop(1, "hsl(" + (angleB % 360) + ",100%, 50%)");   // end color
  ctx.fillStyle = gr;                                            // set as fill style
  ctx.fillRect(0, 0, 500, 150);                                  // fill area
}

// demo loop
(function anim() {
  createGradient();
  ctx.clearRect(8,8,484,134);
  // =========> DRAW YOUR FRONT OBJECTS HERE <=========
  angleA += stepA;                                               // increase angles
  angleB += stepB;
  requestAnimationFrame(anim)
})();
<canvas width=500></canvas>

In the demo above the start and end colors are more or less random, you can instead just give one a head start so the other follows:

Example 2

var ctx = document.querySelector("canvas").getContext("2d"),
    angle = Math.random() * 360,                                 // start angle (for HSL)
    angleDlt = 60,                                               // 60° ahead
    step = 1;                                                    // "speed" for change

function createGradient() {
  var gr = ctx.createLinearGradient(0, 0, 500, 0);               // create gradient
  gr.addColorStop(0, "hsl(" + (angle % 360) + ",100%, 50%)");    // start color
  gr.addColorStop(0.5, "hsl(" + ((angle + (angleDlt/2)) % 360) + ",100%, 50%)");
  gr.addColorStop(1, "hsl(" + ((angle + angleDlt) % 360) + ",100%, 50%)");
  ctx.fillStyle = gr;                                            // set as fill style
  ctx.fillRect(0, 0, 500, 150);                                  // fill area
}

// demo loop
(function anim() {
  createGradient();
  ctx.clearRect(8,8,484,134);
  angle += step;                                               // increase angles
  requestAnimationFrame(anim)
})();
<canvas width=500></canvas>
  • Thank you, but is it possible to add it as a border but still show the rectangles that are in front? – jnnkkkn Mar 12 '15 at 17:29
  • 1
    Sure, (1) draw the rainbow gradient as KenFyrstenberg shows, (2) clear all but the "border" of your canvas. For example, here's a 10px rainbow "border" on the inside of the canvas: `context.clearRect( 10, 10, canvas.width-20, canvas.height-20);` This border is inside the canvas, so be sure any rectangles you draw do not extend within 10px of the canvas's left, right, top or bottom. – markE Mar 12 '15 at 17:35