HTML 5 Canvas - вращение нескольких объектов вокруг собственного источника - PullRequest
0 голосов
/ 06 марта 2019

Я пытаюсь создать объект JavaScript, у которого есть метод, который позволяет прямоугольнику вращаться вокруг своего собственного источника во время обратного вызова rAF.

Что я сделал:

  • Расчет происхождения объекта в пространстве холста.
  • Использование ctx.save() и ctx.restore() - вот где возникают мои проблемы.

Когда я использую save()и restore() методы для перемещения и извлечения сохраненных состояний в вызовах методов для различных объектов, которые либо ничего не изменяют, либо останавливают всю анимацию.

В моем примере вращение применяется глобально кхолст (именно так определяется функциональность в MDN ).Я пытаюсь перевести происхождение вокруг нескольких экземпляров.Я потратил на это часы.

Что-то происходит с механизмом наследования в JavaScript, который не сбрасывает мои преобразования для разных экземпляров объектов прямоугольника в примере кода?

// author: Nicholas Fazzolari

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var xCenterCanvas = innerWidth/2;
var yCenterCanvas = innerHeight/2;

// custom rectangle object
function RectangleCustom(x, y, w, h, color) {
    this.w = w;
    this.h = h;
    this.x = x;
    this.y = y;
    this.color = color;
    this.radians = (Math.PI/180) * 2; // change the last value to change speed
 
    // draws a rectangle at given coordinates
    this.draw = function() {
        ctx.save();
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.w, this.h);
        ctx.restore();
    }
    
    // rotates the rectangle around it's center relative to a given xy position
    this.rotateRect = function() {
        ctx.save();
        ctx.translate(this.x + this.w * 0.5, this.y + this.h * 0.5);
        ctx.rotate(this.radians);
        ctx.translate(-this.x -this.w * 0.5, -this.y - this.h * 0.5);
        //ctx.restore()
    }
}

// singleton rectangles
var bkgRectangle = new RectangleCustom(0, 0, innerWidth, innerHeight, "#212121");
var redRectangle = new RectangleCustom(xCenterCanvas - 64, yCenterCanvas - 64, 128, 128, "#F44336");

// main animation loop
function mainAnimationLoop() {
    // runs animation and clears the canvas each call
    requestAnimationFrame(mainAnimationLoop);
    ctx.clearRect(0, 0, innerWidth, innerHeight);
    
    bkgRectangle.draw();
    redRectangle.draw();
    redRectangle.rotateRect();
}

mainAnimationLoop();

Я пытался вращать несколько прямоугольников вокруг собственного источника в разных положениях без анимации, используя save() и restore() - что сработало.

Кроме того,Я попытался переместить метод rotate внутри метода draw, и результаты были такими же.Мое обоснование было то, что вращение будет применяться как вызов функции в draw() - обоснование было явно неверным.

Любое понимание решения было бы очень полезно.Я включил ссылку на ручку на codepen , чтобы увидеть концепцию в движении.

1 Ответ

2 голосов
/ 06 марта 2019

Вместо того, чтобы рисовать риты в (this.x, this.y), вы можете нарисовать их в 0,0 и перевести их в (this.x, this.y);

// author: Nicholas Fazzolari

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var xCenterCanvas = innerWidth/2;
var yCenterCanvas = innerHeight/2;

// custom rectangle object
function RectangleCustom(x, y, w, h, color) {
    this.w = w;
    this.h = h;
    this.x = x;
    this.y = y;
    this.color = color;
    this.radians = (Math.PI/180) * 2; // change the last value to change speed
    this.rotation = 0;
 
    // draws a rectangle at given coordinates
    this.draw = function() {
        this.rotation += this.radians;
        ctx.save();
        ctx.fillStyle = this.color;
        ctx.translate(this.x, this.y);
        ctx.rotate(this.rotation);
        ctx.fillRect(0,0, this.w, this.h);
        ctx.restore();
    }
    
    
    this.update = function() {
         // animation updates
     }
}

// singleton rectangles
var bkgRectangle = new RectangleCustom(0, 0, innerWidth, innerHeight, "#212121");
var redRectangle = new RectangleCustom(xCenterCanvas - 64, yCenterCanvas - 64, 128, 128, "#F44336");

// main animation loop
function mainAnimationLoop() {
    // runs animation and clears the canvas each call
    requestAnimationFrame(mainAnimationLoop);
    ctx.clearRect(0, 0, innerWidth, innerHeight);
    
    bkgRectangle.draw();
    redRectangle.draw();
    
}

mainAnimationLoop();
<canvas></canvas>
...