Холст HTML5 DrawImage под углом

Я экспериментирую с анимацией в <canvas> и не могу понять, как нарисовать изображение под углом. Желаемый эффект — несколько изображений, нарисованных как обычно, при этом одно изображение медленно вращается. (Это изображение не в центре экрана, если это имеет значение).


person Greg    schedule 25.09.2010    source источник


Ответы (3)


Вам необходимо изменить матрицу преобразования, прежде чем рисовать изображение, которое вы хотите повернуть.

Предположим, что изображение указывает на объект HTMLImageElement.

var x = canvas.width / 2;
var y = canvas.height / 2;
var width = image.width;
var height = image.height;

context.translate(x, y);
context.rotate(angleInRadians);
context.drawImage(image, -width / 2, -height / 2, width, height);
context.rotate(-angleInRadians);
context.translate(-x, -y);

Координаты x, y — это центр изображения на холсте.

person Jakub Wieczorek    schedule 25.09.2010
comment
вместо вращения/перемещения в конце вы можете сделать context.save() и context.restore() до и после выполнения преобразований и рисования. - person Matthew Crumley; 25.09.2010
comment
Хотя использование save()/restore() может показаться более чистым, оно было бы гораздо более неэффективным. Движок должен будет хранить/восстанавливать все свойства контекста, а не только те, которыми мы здесь манипулируем. Это имеет значение в чувствительном пути кода. - person Jakub Wieczorek; 25.09.2010
comment
Для другого примера см. этот (повторяющийся) вопрос и ответ: Набор шкалы с использованием холста HTML5 — поворот относительно произвольной точки. - person Phrogz; 10.01.2011
comment
@JakubWieczorek Нет, движок может легко сохранять грязные флаги для каждого свойства контекста и лениво сохранять (а затем восстанавливать) только те, которые затронуты между save() и restore(). Ручная настройка — это преждевременная оптимизация. - person s4y; 29.11.2015
comment
как это влияет на производительность игры, т.е. каждый игровой объект анимирован и является изображением? - person Nikos; 28.10.2016

Я написал функцию (на основе ответа Якуба), которая позволяет пользователю рисовать изображение в положении X, Y на основе пользовательского поворота в пользовательской точке вращения:

function rotateAndPaintImage ( context, image, angleInRad , positionX, positionY, axisX, axisY ) {
  context.translate( positionX, positionY );
  context.rotate( angleInRad );
  context.drawImage( image, -axisX, -axisY );
  context.rotate( -angleInRad );
  context.translate( -positionX, -positionY );
}

Затем вы можете назвать это так:

var TO_RADIANS = Math.PI/180; 
ctx = document.getElementById("canvasDiv").getContext("2d");
var imgSprite = new Image();
imgSprite.src = "img/sprite.png";

// rotate 45º image "imgSprite", based on its rotation axis located at x=20,y=30 and draw it on context "ctx" of the canvas on coordinates x=200,y=100
rotateAndPaintImage ( ctx, imgSprite, 45*TO_RADIANS, 200, 100, 20, 30 );
person Yaume    schedule 05.06.2014

Интересно, что первое решение сработало для стольких людей, не дало нужного мне результата. В итоге пришлось сделать так:

ctx.save();
ctx.translate(positionX, positionY);
ctx.rotate(angle);
ctx.translate(-x,-y);
ctx.drawImage(image,0,0);
ctx.restore();

где (positionX, positionY) — это координаты на холсте, в которых я хочу, чтобы изображение располагалось, а (x, y) — это точка на изображении, в которой я хочу, чтобы изображение вращалось.

person PetrolHead    schedule 24.10.2017