Поверните мозаичные изображения индивидуально в HTML холст - PullRequest
2 голосов
/ 22 января 2020

У меня есть некоторый код в моей игре, который вращает значок на холсте следующим образом:

if (rotate > 0) {
    context.translate(canvasWidth / 2, canvasHeight / 2);
    context.rotate(rotate);
    context.translate(-canvasWidth / 2, -canvasHeight / 2);
}

Ничего, чего вы раньше не видели. Я также добавил функцию, которая накладывает значки на большие холсты следующим образом:

var x = 0;
var y = 0;

for (var i = 0; i < totalUnits; i++) {
    context.drawImage(img, x, y);

    if (i != 0 && (i + 1) % level == 0) {
        x = 0;
        y += 72;
    }

    else {
        x += 72;
    }
}

Обратите внимание, что переменная level может быть любым целым числом, а totalUnits - это ее квадрат, если он больше чем 1, например, если я укажу level как 2, то на моем холсте будут нарисованы 4 изображения: 2 поперек и 2 вниз. Также обратите внимание, что мои изображения всегда имеют размер 72х72 пикселей, следовательно, 72 выше. Опять же, ничего особенного.

Моя трудность заключается в том, чтобы повернуть изображения в пределах холста таким образом, чтобы отдельное изображение поворачивалось на значение, переданное в rotate, но не на сам холст целиком. Я попытался добавить следующий код со многими перестановками, заменив вышеуказанный вызов на context.drawImage в for l oop, но пока безуспешно:

context.translate(72 / 2, 72 / 2);
context.rotate(rotate);
context.drawImage(img, x, y);
context.rotate(0);
context.translate(-72 / 2, -72 / 2);

Чтобы помочь визуализировать эффект, я пытаясь достичь, вот что нарисовано, когда вращение установлено в 0:

enter image description here

И вот что я хотел бы, чтобы мои мозаичные изображения на холст, чтобы выглядеть, когда повернут на 45 градусов (например): enter image description here

Я хотел бы отметить, что я не пытаюсь повернуть весь холст - я знаю, как чтобы сделать это, но это не тот эффект, которого я пытаюсь достичь, так как мне нужно, чтобы значки оставались в своих отдельных положениях x, y. Кроме того, вращение всего холста создает проблемы с обрезанным углом.

Любая помощь будет принята с благодарностью!

1 Ответ

2 голосов
/ 22 января 2020

Самый простой способ - переписать текущее преобразование

ctx.setTransform(scale, 0, 0, scale, x, y); 
ctx.rotate(rotate); 
ctx.drawImage(img, -img.width / 2, -img.height/ 2); 

Нарисуйте центр изображения в x, y, поверните на rotate вокруг img центра и масштабируйте на scale. Шкала 1 не является шкалой.

Чтобы сбросить преобразование по умолчанию, например, перед очисткой холста

ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

Поскольку под капотом ctx.rotate требуется как минимум 1 грех и 1 cos, 12 временных чисел, а затем 12 умножений и 8 дополнений. Если масштабирование равномерное (одинаковый масштаб для x и y), то для создания матрицы быстрее использовать упрощенный метод. Обратите внимание, что если масштаб всегда равен 1, вам не нужен масштаб`

Также, когда изображение загружается, вы можете установить точку поворота в качестве свойств изображения.

Когда изображение загружается, установите смещение

img.offset_x = - img.naturalWidth / 2;  // NOTE I use snake_case for the property names
img.offset_y = - img.naturalHeight / 2; // so that the names will never clash with
                                        // future changes to the standard  

Чтобы отобразить это изображение

const ax = Math.cos(rotate) * scale;
const ay = Math.sin(rotate) * scale;
ctx.setTranform(ax, ay, -ay, ax, x, y);
ctx.drawImage(img, img.offset_x, img.offset_y);
...