Spec-Zone.ru › Web APIs

Компоновка и обрезка

  • Предыдущая
  • Следующая

Во всех наших предыдущих примерах фигуры всегда рисовались друг на друге. Это вполне достаточно для большинства ситуаций, но оно ограничивает порядок построения составных фигур. Однако мы можем изменить это поведение, установив свойство globalCompositeOperation. Кроме того, свойство clip позволяет скрыть нежелательные части фигур.

globalCompositeOperation

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

globalCompositeOperation = type

Это задаёт тип операции компоновки, применяемой при рисовании новых фигур, где тип — строка, определяющая, какая из двенадцати операций компоновки должна быть использована.

Обрезка по траекториям

Область обрезки — это обычная фигура холста, но она действует как маска для скрытия нежелательных частей фигур. Это показано на изображении ниже. Красная звёздчатая фигура — это наша область обрезки. Всё, что попадает за пределы этой области, не будет нарисована на холсте.

A canvas with a star outlined in red color. The inside of the star is transparent, as portrayed by the grid squares inside the star being clearly visible whereas the grid squares lying outside the star are blurred.

Если сравнить области обрезки со свойством globalCompositeOperation выше, то мы увидим два режима компоновки, которые достигают более или менее того же эффекта в source-in и source-atop. Самые важные различия между ними заключаются в том, что области обрезки никогда фактически не рисуются на холсте, и область обрезки никогда не изменяется при добавлении новых фигур. Это делает области обрезки идеальными для рисования нескольких фигур в ограниченной области.

В главе о рисовании фигур я упомянул только методы stroke() и fill(), но есть третий метод, который мы можем использовать с траекториями, называемый clip().

clip()

Преобразует траекторию, которая в данный момент строится, в текущую область обрезки.

Вы используете clip() вместо closePath() для закрытия траектории и превращения её в область обрезки вместо обводки или заливки траектории.

По умолчанию элемент <canvas> имеет область обрезки, размер которой точно такой же, как размер холста. Другими словами, обрезка не выполняется.

Пример clip

В этом примере мы будем использовать круговую область обрезки для ограничения рисования набора случайных звёзд в определённом регионе.

function draw() {
  const ctx = document.getElementById("canvas").getContext("2d");
  ctx.fillRect(0, 0, 150, 150);
  ctx.translate(75, 75);

  // Create a circular clipping path
  ctx.beginPath();
  ctx.arc(0, 0, 60, 0, Math.PI * 2, true);
  ctx.clip();

  // Draw background
  const linGrad = ctx.createLinearGradient(0, -75, 0, 75);
  linGrad.addColorStop(0, "#232256");
  linGrad.addColorStop(1, "#143778");

  ctx.fillStyle = linGrad;
  ctx.fillRect(-75, -75, 150, 150);

  generateStars(ctx);
}

function generateStars(ctx) {
  for (let j = 1; j < 50; j++) {
    ctx.save();
    ctx.fillStyle = "#fff";
    ctx.translate(
      75 - Math.floor(Math.random() * 150),
      75 - Math.floor(Math.random() * 150),
    );
    drawStar(ctx, Math.floor(Math.random() * 4) + 2);
    ctx.restore();
  }
}

function drawStar(ctx, r) {
  ctx.save();
  ctx.beginPath();
  ctx.moveTo(r, 0);
  for (let i = 0; i < 9; i++) {
    ctx.rotate(Math.PI / 5);
    if (i % 2 === 0) {
      ctx.lineTo((r / 0.525731) * 0.200811, 0);
    } else {
      ctx.lineTo(r, 0);
    }
  }
  ctx.closePath();
  ctx.fill();
  ctx.restore();
}

В первых строках кода мы рисуем чёрную прямоугольную область размером с холст в качестве фона, затем перемещаем начало координат в центр. Затем мы создаём круговую область обрезки, рисуя дугу и вызывая clip(). Области обрезки также являются частью состояния сохранения холста. Если бы мы хотели сохранить исходную область обрезки, мы могли бы сохранить состояние холста до создания новой.

Всё, что рисуется после создания области обрезки, будет отображаться только внутри этой области. Это чётко видно на линейном градиенте, который рисуется дальше. После этого рисуется набор из 50 случайных по положению и масштабу звёзд, используя пользовательскую функцию drawStar(). Опять же, звёзды отображаются только внутри определённой области обрезки.

Обратная область обрезки

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

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

function draw() {
  const canvas = document.getElementById("canvas");
  if (canvas.getContext) {
    const ctx = canvas.getContext("2d");
    ctx.translate(75, 75);

    // Clipping path
    ctx.beginPath();
    ctx.rect(-75, -75, 150, 150); // Outer rectangle
    ctx.arc(0, 0, 60, 0, Math.PI * 2, true); // Hole anticlockwise
    ctx.clip();

    // Draw background
    const linGrad = ctx.createLinearGradient(0, -75, 0, 75);
    linGrad.addColorStop(0, "#232256");
    linGrad.addColorStop(1, "#143778");

    ctx.fillStyle = linGrad;
    ctx.fillRect(-75, -75, 150, 150);

    generateStars(ctx);
  }
}
  • Предыдущая
  • Следующая

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API