Naltroc
Naltroc

Reputation: 1007

Canvas rotation - fixed background, moving foreground

Goal

The stripes in the background remain fixed while the cones rotate about the center.

Current State

live demo:

https://codepen.io/WallyNally/pen/yamGYB

/*
The loop function is around line 79.
Uncomment it to start the animation. 
*/

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

var W = c.width = window.innerWidth; 
var H = c.height = window.innerHeight;


var Line = function() {
    this.ctx = ctx;
  this.startX = 0;
  this.startY = 0;
  this.endX = 0;
  this.endY = 0;
    this.direction = 0;
    this.color = 'blue';

    this.draw = function() {
        this.ctx.beginPath();
    this.ctx.lineWidth = .1;
        this.ctx.strokeStlye = this.color;
        this.ctx.moveTo(this.startX, this.startY);
        this.ctx.lineTo(this.endX, this.endY);
    this.ctx.closePath();
    this.ctx.stroke();
    }

    this.update = function() {
    //for fun 

    if (this.direction == 1) {
      this.ctx.translate(W/2, H/2);
      this.ctx.rotate(-Math.PI/(180));
    }
    }//this.update()
}//Line();

objects=[];

function initLines() {
    for (var i =0; i < 200; i++) {
        var line = new Line();
        line.direction = (i % 2);

    if (line.direction == 0) {
      line.startX = 0;
      line.startY = -H + i * H/100;
      line.endX = W + line.startX;
      line.endY = H + line.startY;
    }
    if (line.direction == 1) {
      line.startX = 0;
      line.startY = H - i * H/100;
      line.endX = W - line.startX;
      line.endY = H - line.startY;
    }
    objects.push(line);
    line.draw();
    }
}

initLines(); 

function render(c) {
  c.clearRect(0, 0, W, H);
  for (var i = 0; i < objects.length; i++) 
    { 
      objects[i].update();
      objects[i].draw();
    }
}

function loop() {
  render(ctx);
  window.requestAnimationFrame(loop);
}

//loop();

What I have tried

The translate(W/2, H/2) should place the context at the center of the page, then this.ctx.rotate(-Math.PI/(180)) should rotate it one degree at a time. This is the part that is not working.

Using save()and restore() is the proper way to keep some parts of an animation static while others move. I placed the save and restore in different parts of the code to no avail. There are one of two types of result : Either a new entirely static image is produced, or some erratic animation happens (in the same vein of where it is now).

Upvotes: 0

Views: 155

Answers (1)

FallenNode
FallenNode

Reputation: 213

Here is the changed pen: http://codepen.io/samcarlinone/pen/LRwqNg

You needed a couple of changes:

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

var W = c.width = window.innerWidth; 
var H = c.height = window.innerHeight;

var angle = 0;

var Line = function() {
    this.ctx = ctx;
    this.startX = 0;
    this.startY = 0;
    this.endX = 0;
    this.endY = 0;
    this.direction = 0;
    this.color = 'blue';

    this.draw = function() {
        this.ctx.beginPath();
    this.ctx.lineWidth = .1;
        this.ctx.strokeStlye = this.color;
        this.ctx.moveTo(this.startX, this.startY);
        this.ctx.lineTo(this.endX, this.endY);
    this.ctx.closePath();
    this.ctx.stroke();
    }

    this.update = function() {
    //for fun 
    if (this.direction == 1) {
      this.ctx.translate(W/2, H/2);
      this.ctx.rotate(angle);
      this.ctx.translate(-W/2, -H/2);
    }
    }//this.update()
}//Line();

objects=[];

function initLines() {
    for (var i =0; i < 200; i++) {
        var line = new Line();
        line.direction = (i % 2);

    if (line.direction == 0) {
      line.startX = 0;
      line.startY = -H + i * H/100;
      line.endX = W + line.startX;
      line.endY = H + line.startY;
    }
    if (line.direction == 1) {
      line.startX = 0;
      line.startY = H - i * H/100;
      line.endX = W - line.startX;
      line.endY = H - line.startY;
    }
    objects.push(line);
    line.draw();
    }
}

initLines(); 

function render(c) {
  c.clearRect(0, 0, W, H);
  for (var i = 0; i < objects.length; i++) 
    { 
      ctx.save();
      objects[i].update();
      objects[i].draw();
      ctx.restore();
    }
}

function loop() {
  render(ctx);
  window.requestAnimationFrame(loop);

  angle += Math.PI/360;
}

loop();

First I added a variable to keep track of rotation and increment it in the loop

Second I save and restore for each individual line, alternatively if all lines were going to perform the same transformation you could move that code before and after the drawing loop

Third to get the desired affect I translate so the center point is in the middle of the screen, then I rotate so that the lines are rotated, then I translate back because all the lines have coordinates on the interval [0, H]. Instead of translating back before drawing another option would be to use coordinates on the interval [-(H/2), (H/2)] etc.

Upvotes: 1

Related Questions