Значит, для отзеркаливания картинки мы не можем просто добавить >cx.scale(-1, 1)
перед вызовом >drawImage
– наша картинка уедет с холста и не будет видна. Можно было бы подправить координаты, передаваемые в >drawImage
, чтобы компенсировать этот сдвиг. Другой вариант действий, когда код рисования ничего не знает про масштабирование, заключается в изменении направления оси.
Есть несколько других методов кроме масштабирования, влияющих на координатную систему холста. Нарисованные формы можно поворачивать методом >rotate
и сдвигать методом >translate
. Интересно, что все трансформации накапливаются, то есть каждая последующая происходит относительно предыдущих.
Значит, если мы дважды сдвинем изображение на 10 пикселей по горизонтали, то всё будет нарисовано на 20 пикселей правее. Если мы сначала сдвинем начало отсчёта на (50, 50), а затем повернём всё на 20 градусов (0,1π радиан), поворот произойдёт вокруг точки (50, 50).
А если мы сначала повернём всё на 20 градусов, а уже затем сдвинем на (50, 50), то преобразование случится в повёрнутой системе координат, что приведёт к иному результату. Порядок преобразований имеет значение.
Чтобы отзеркалить картинку относительно вертикали на заданной позиции x, мы делаем следующее:
>function flipHorizontally(context, around) {
> context.translate(around, 0);
> context.scale(-1, 1);
> context.translate(-around, 0);
>}
Мы сдвигаем ось Y туда, где нам нужно расположить наше зеркало, проводим отзеркаливание, и сдвигаем ось Y обратно на полагающееся место в зеркальной вселенной. Следующий рисунок объясняет, как это работает:
Тут показаны системы координат до и после отзеркаливания относительно центральной линии. Если мы нарисуем треугольник в положительной полуплоскости относительно Y, он будет находиться на месте треугольника 1. Вызов >flipHorizontally
сначала сдвигает его вправо, на место треугольника 2. Затем происходит масштабирование, и треугольник оказывается на месте 3. Он должен быть не там, если нам надо отзеркалить его относительно заданной линии. Второй вызов >translate
исправляет это – он «отменяет» изначальный сдвиг и помещает треугольник на позицию 4.
Теперь можно нарисовать отзеркаленного персонажа на позиции (100, 0), перевернув мир относительно вертикали изображения персонажа.
>
>
> var cx = document.querySelector("canvas").getContext("2d");
> var img = document.createElement("img");
> img.src = "img/player.png";
> var spriteW = 24, spriteH = 30;
> img.addEventListener("load", function() {
> flipHorizontally(cx, 100 + spriteW / 2);