Сохранение и загрузка состояния канваса

Сейчас мы разберемся как сохранять и загружать состояния холста.
Когда рисунки становятся более сложными, Вам может понадобится вернуться на предыдущее состояние, Вы можете захотеть управлять текущим или предыдущим состоянием.
Для этого нам пригодятся два метода:

  • context.save() — сохраняет состояние
  • context.restore() — восстанавливает состояние

Мы можем сохрнаять и загружать состояния из стэка.
Вот мы и выяснили что холст сохраняет состояния в стэке состояний.

// Rect 1
context.fillStyle = "red";
context.fillRect(240, 100, 120, 120);
context.save();
// Rect 2
context.fillStyle = "green";
context.fillRect(390, 100, 120, 120);
context.save();
// Rect 3
context.fillStyle = "blue";
context.fillRect(540, 100, 120, 120);
context.save();

// Rect 4
context.restore();
context.fillRect(240, 300, 120, 120);
// Rect 5
context.restore();
context.fillRect(390, 300, 120, 120);
// Rect 6
context.restore();
context.fillRect(540, 300, 120, 120);

В нашем примере… последнее сохраненное состояние будет синий квадрат. Поэтому, если мы попробуем после него нарисовать квадраты не указывая цвет, то они будут синими. Поэтому восстанавливая состояния, мы получаем тот цвет, который был в стеке.

Сохранить канвас как рисунок

Всё что нужно для того чтобы получить картинку — это один метод встроенный в канвас.
Т.е. мы получаем dataUrl канваса, а затем вставляем его как src объекта изображения. И теперь можем сохранить его у себя на компе просто скачав эту картинку.

let dataURL = canvas.toDataURL();
document.querySelector("#canvasImg").src = dataURL;

Паттерны

За паттерны в канвас отвечает метод — context.createPatter(image, repetition),
который принимает два параметра — изображение, и повторение, которая устанавливает направление заполнения.
Второй параметр может принимать следующие аргументы
* repeat — оба направления
* repeat-x — только горизонтально
* repeat-y — только вертикально
* no-repeat — никак

const patternImage = new Image();
    patternImage.src = './pattern.jpg';

    patternImage.onload = () => {
        const pattern = context.createPattern(patternImage, 'repeat');
        context.fillStyle=pattern;
        context.fillRect(0, 0, 900, 450);

    }

Как видим, после того, как мы установим паттерн, его нужно применить. Т.е. по сути мы закрашиваем прямоугольник нашим паттерном.

Градиент

За создание градиентов отвечают два метода
* context.createLinearGradient(x1,y1,x2,y2)
* context.createRadialGradient(x1,y1,r1,x2,y2,r2)

Первый принимает 4 параметра — первые два это координаты стартовой точки градиента, вторые два координаты конечной точки градиента.
Второй принимает 6 параметров — первые два координаты стартовой точки окружности градиента, второй параметр — радиус стартовой окружности. Следующие два параметра это координаты конечной окружности. Последний параметр — радиус конечной окружности.

Так мы укажем расположение градиента.
А теперь нужно указать цвет

gradient.addColorStop(stop, color);

Эта функция принимает два параметра — первый, значение между 0 и 1. Которое означает начало или конец градиента. А цвет. Означает цвет в стоп позиции.

Теперь применим этот цвет к нашему объекту.

let gradient = context.createLinearGradient(240, 20, 660, 440);
    gradient.addColorStop(0, 'red');
    gradient.addColorStop(1, 'white');


    context.strokeStyle='blue';
    context.lineWidth=4;
    context.fillStyle=gradient;
    context.rect(240, 20, 420, 420);
    context.stroke();
    context.fill();

Таже мы можем установить больше стоппозиций градиента

let gradient = context.createLinearGradient(240, 20, 660, 440);
    gradient.addColorStop(0, 'red');
    gradient.addColorStop(0.25, 'green');
    gradient.addColorStop(0.5, 'yellow');
    gradient.addColorStop(0.75, 'blue');
    gradient.addColorStop(1, 'white');

Ну и нарисуем радиальный градиент:

let gradient = context.createRadialGradient(570, 380, 300, 570, 300, 20);
    gradient.addColorStop(0, 'red');
    gradient.addColorStop(0.25, 'green');
    gradient.addColorStop(0.5, 'yellow');
    gradient.addColorStop(0.75, 'blue');
    gradient.addColorStop(1, 'white');