HTML5: Canvas. Трансформация

Вращение
Перемещение
Сохранение и восстановление контекста
Масштабирование
Функция setTransform()

Вращение

Вращение вызывается функцией rotate().


<canvas id="rotate_demo" width="300" height="250" style = "border:2px solid black"></canvas>

<script>
    var canvas = document.getElementById("rotate_demo");
    var context = canvas.getContext("2d");
    
    var angle = 40; // угол поворота
    
    context.fillStyle = "silver";
    context.fillRect(0, 0, canvas.width, canvas.height);
    context.translate(canvas.width / 2, canvas.height / 2);
    
    drawBezier(angle, "darkturquoise");
    drawBezier(angle, "deeppink");
    drawBezier(angle, "gold");
    drawBezier(angle, "mediumvioletred");
    drawBezier(angle, "yellow");
    drawBezier(angle, "teal");
    drawBezier(angle, "chartreuse");
    drawBezier(angle, "magenta");
    drawBezier(angle, "red");
    
    function drawBezier(angle, color)
    {
        context.fillStyle = color;
        context.lineWidth = 7;
        context.shadowOffsetX = 3;
        context.shadowOffsetY = 3;
        context.shadowBlur = 5;
        context.shadowColor = "gray";

        var xStart = 0;
        var yStart = 0;
        var xControl1 = 90;
        var yControl1 = 20;
        var xControl2 = -60;
        var yControl2 = 60;
        var xEnd = 60;
        var yEnd = 60;
        
        // переводим градусы в радианы
        var angleInRadians = angle * Math.PI/180;
        context.rotate(angleInRadians);

        context.beginPath();
        context.moveTo(xStart, yStart);

        context.bezierCurveTo(xControl1, yControl1, 
                xControl2, yControl2, 
                xEnd, yEnd);
        context.fill();
    }
</script>

Перемещение

Объекты на холсте можно перемещать с помощью функции translate(). Сама функция применяется к контексту холста и имеет два параметра - новые значения координат для перемещения. В примере нарисуем серый квадрат в точке 0,0. Затем остальные квадраты будем рисовать в новых позициях. При этом предыдущий сдвиг запоминается и перемещение происходит относительно новой позиции.

Ваш браузер не поддерживает canvas

<canvas id="translate_demo" width="500" height="170" style = "border:2px solid black">Ваш браузер не поддерживает canvas</canvas>
    
<script>
    var canvas = document.getElementById("translate_demo");
    var context = canvas.getContext("2d");
    
    // Размер стороны квадрата
    var size = 40;
    
    drawSquare( 0, 0, "gray" );
    drawSquare( size, size, "red" );
    drawSquare( size, size, "orange");
    drawSquare( size, -size, "blue" );
    drawSquare( size, 0, "pink" );
    drawSquare( size, -size, "purple");
    drawSquare( 2 * size, size, "green" );
    
    function drawSquare(translateH, translateV, color)
    {
        context.fillStyle = color;
        context.translate(translateH, translateV);
        context.fillRect(0, 0, size, size);
    }
</script>

В некоторых ситуациях подобное поведение, когда состояние сдвига запоминается, бывает неудобным. Чтобы решить проблемы, используют пару функций save() и restore().

Сохранение и восстановление контекста

Если какое-то свойство контекста изменить, то оно повлияет на все последующие. Есть два метода контекста save() и restore(), которые сохраняют и восстанавливают последнее сохраненное состояние. Мы можем не сбрасывать все свойства на начальные, а просто вызывать эти функции.


context.save();
context.textAlign = 'center';
context.font = "bold italic 30px sans-serif";
context.strokeText("Hello Kitty", 300, 300);
context.restore();
context.fillText("Hello Kitty", 400, 400);

Функции можно вызывать несколько раз в разных местах. Все состояния будут запоминаться в массиве и восстанавливаться при вызове парной функции restore(). Главное, не запутаться в них.

Масштабирование

Масштабирование производится через функцию scale(). Для примера воспользуемся сохранением и восстановлением контекста.

Ваш браузер не поддерживает canvas

<canvas id="scale_demo" width="500" height="170" style = "border:2px solid black">Ваш браузер не поддерживает canvas</canvas>
    
<script>
    var canvas = document.getElementById("scale_demo");
    var context = canvas.getContext("2d");
    
    drawSquare(25, 25, 1.4, 1.4, "gray", true);
    drawSquare(25, 25, 1.0, 1.1, "red", true);
    drawSquare(25, 25, 0.7, 0.7, "orange", true);
    drawSquare(100, 25, 1.4, 1.4, "blue", false );
    drawSquare(100, 25, 1.0, 1.1, "pink", true);
    drawSquare(100, 25, 0.7, 0.7, "purple", false);
    
    function drawSquare(xPos, yPos, scaleH, scaleV, color, save)
    {
        if (save) {
            context.save();
        }
        
        context.fillStyle = color;
        var size = 40;
        context.translate(xPos, yPos);
        context.scale(scaleH, scaleV);
        context.fillRect(0, 0, size, size);
        
        if(save){
            context.restore();
        }
    }
</script>

Собственный метод drawSquare() имеет последний параметр save, который указывает, нужно ли запоминать состояние контекста. При рисовании первых трёх квадратов мы запоминали состояние контекста и все фигуры рисовались относительно одной точки (0.0). Затем выводим синий квадрат уже со смещением, присвоив значение false для запоминания контекста. Следующий розовый квадрат также смещается от текущей точки синего квадрата, а затем фиолетовый квадрат никуда не смещается, а только масштабируется.

Зеркальное отображение

Сочетание функций translate() и scale() позволяет сделать зеркальное отображение.

Ваш браузер не поддерживает canvas

<canvas id="mirror_demo" width="300" height="240" style ="border:2px solid black">Ваш браузер не поддерживает canvas</canvas>
    
<script>

    window.onload = function() {
        var canvas = document.getElementById('mirror_demo');
        var context = canvas.getContext('2d');
        var image = new Image();
        
        var xPos = 75;
        var yPos = 15;
        var imageWidth = 90;
        var imageHeight = 90;
        
        var reflectY = (2 * yPos) + (2 * imageHeight + 1.5);
        
        image.onload = function() {
           context.drawImage(image, xPos, yPos, imageWidth, imageHeight);
                    
            context.translate(0, reflectY);
            context.scale(1, -1);
            
            context.drawImage(image, xPos, yPos, imageWidth, imageHeight);
        };
          
        image.src = '../images/star.jpg';
    }
</script>

Вызов context.scale(1, -1) поворачивает изображение по вертикали.

Функция setTransform()

Специальная функция setTransform() позволяет объединить несколько видов трансформации.


setTransform(scaleX, skewY, skewX, scaleY, translateX, translateY)

В шести параметрах функции вы указываете коэффициенты масштабирования, сдвига и перемещения.

Ваш браузер не поддерживает canvas
Реклама