I am trying to create a colour-changing spiral animation. The colour of the spiral should update based on the position of the mouse and should only update when the mousemove or touchmove events are triggered/fired. The problem is that when the page loads, the user moves the mouse, a colour is computed and then assigned to c.strokeStyle and then won't change. I don't think this should be happening as the console.log("rgb("+Math.round(r)+","+Math.round(g)+","+Math.round(b)+")") does in fact work and shows the value in the console. The code is as follows:

var canvas = document.getElementById('canvas');
var c = canvas.getContext('2d');

canvas.width = innerWidth;
canvas.height = innerHeight;

// mouse and related functions with event listeners
var mouse = {
  x: undefined,
  y: undefined
}

window.addEventListener('mousemove', function(event) {
  mouse.x = event.x;
  mouse.y = event.y;
  drawSpiral();
})

window.addEventListener('touchmove', function (event) {
  mouse.x = event.x;
  mouse.y = event.y;
  drawSpiral();
})

function generateRGB() {
  // handled as rgb
  var r = map_range(mouse.x, 0, canvas.width, 0, 255);
  var g = map_range(mouse.y, 0, canvas.height, 0, 255);;
  var b = map_range(mouse.x+mouse.y, 0, canvas.width, 0, 255);;

  // console.log("rgb("+Math.round(r)+","+Math.round(g)+","+Math.round(b)+")")
  return "rgb("+Math.round(r)+","+Math.round(g)+","+Math.round(b)+")";

}

// used to map the mouse x, y to 0, 255 for colour
function map_range(value, low1, high1, low2, high2) {
    return low2 + (high2 - low2) * (value - low1) / (high1 - low1);
}

// spiral drawing

var distance = 800;

var x = 10;
var y = 10;

function updatePosition(xChange, yChange) {
  x += xChange;
  y += yChange;
}


function drawSpiral(colour=generateRGB()) {
  c.beginPath()
  //c.fillRect(0, 0, canvas.width, canvas.height)
  c.strokeStyle = colour;

  while (distance > 0) {

    c.moveTo(x, y);

    c.lineTo(x+distance, y); // move right
    updatePosition(distance, 0);
    distance -= 6;

    c.lineTo(x, y+distance); // move down
    updatePosition(0, distance);

    c.lineTo(x-distance, y); // move left
    updatePosition(-distance, 0);
    distance -= 6;

    c.lineTo(x, y-distance); // move up
    updatePosition(0, -distance);

    c.stroke();
  }

  c.closePath();
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Square Spiral</title>
  </head>
  <body>
    <canvas id="canvas"></canvas>
    <script type="text/javascript" src="main.js"></script>
  </body>
</html>

Any help would be greatly appreciated. Thanks! :)

1 Answers

3
chatnoir On Best Solutions

The problem was that after drawing the spiral the first time, the starting variables x, y and distance take on new values that do not permit the spiral from being painted again in subsequent calls.

They need to be reset to their starting values each time within drawSpiral():

  // re-initialize the starting variables each time drawSpiral is run
  distance = 800;
  x= 10;
  y= 10;

See below for implementation:

var canvas = document.getElementById('canvas');
var c = canvas.getContext('2d');

canvas.width = innerWidth;
canvas.height = innerHeight;

// mouse and related functions with event listeners
var mouse = {
  x: undefined,
  y: undefined
}

window.addEventListener('mousemove', function(event) {
  mouse.x = event.x;
  mouse.y = event.y;
  drawSpiral();
})

window.addEventListener('touchmove', function (event) {
  mouse.x = event.x;
  mouse.y = event.y;
  drawSpiral();
})

function generateRGB() {
  // handled as rgb
  var r = map_range(mouse.x, 0, canvas.width, 0, 255);
  var g = map_range(mouse.y, 0, canvas.height, 0, 255);;
  var b = map_range(mouse.x+mouse.y, 0, canvas.width, 0, 255);;

 // console.log("rgb("+Math.round(r)+","+Math.round(g)+","+Math.round(b)+")")
  return "rgb("+Math.round(r)+","+Math.round(g)+","+Math.round(b)+")";

}

// used to map the mouse x, y to 0, 255 for colour
function map_range(value, low1, high1, low2, high2) {
    return low2 + (high2 - low2) * (value - low1) / (high1 - low1);
}

// spiral drawing

var distance = 800;

var x = 10;
var y = 10;

function updatePosition(xChange, yChange) {
  x += xChange;
  y += yChange;
}


function drawSpiral(colour=generateRGB()) {
  c.beginPath()
  //c.fillRect(0, 0, canvas.width, canvas.height)
  c.strokeStyle = colour;

  //*****************************************
  // reset the starting values
  //*****************************************
  distance = 800;
  x= 10;
  y= 10;
  //*****************************************
  
  while (distance > 0) {

    c.moveTo(x, y);

    c.lineTo(x+distance, y); // move right
    updatePosition(distance, 0);
    distance -= 6;

    c.lineTo(x, y+distance); // move down
    updatePosition(0, distance);

    c.lineTo(x-distance, y); // move left
    updatePosition(-distance, 0);
    distance -= 6;

    c.lineTo(x, y-distance); // move up
    updatePosition(0, -distance);

    c.stroke();
  }
  
  c.closePath();
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Square Spiral</title>
  </head>
  <body>
    <canvas id="canvas"></canvas>
    <script type="text/javascript" src="main.js"></script>
  </body>
</html>