W3docs

Градиенты Canvas

Градиенты HTML5 Canvas — шаблоны цвета для заливки кругов, прямоугольников, линий, текста и других фигур. Линейные и радиальные градиенты с примерами.

Градиент — это плавный переход от одного цвета к другому. Градиенты HTML5 Canvas позволяют заливать или обводить фигуры — круги, прямоугольники, линии, текст, произвольные пути — таким многоцветным переходом вместо сплошного однотонного цвета.

В этой главе рассматриваются три типа градиентов, которые можно создать в контексте 2D canvas, то, как координатные параметры управляют направлением и размером, как addColorStop() расставляет цвета вдоль градиента, а также несколько готовых к запуску примеров (вертикальный, диагональный, заливка текста и пути, радиальное свечение). Если вы только знакомитесь с canvas API, начните с введения в HTML5 Canvas, затем изучите рисование фигур и путей и ознакомьтесь с тем, как устроена система координат canvas.

Как работают градиенты canvas

Работа с градиентом всегда следует одним и тем же четырём шагам:

  1. Создайте объект градиента с помощью одного из фабричных методов контекста:
    • ctx.createLinearGradient(x0, y0, x1, y1) — линейный (направленный) градиент.
    • ctx.createRadialGradient(x0, y0, r0, x1, y1, r1) — радиальный (круговой) градиент.
    • ctx.createConicGradient(startAngle, x, y) — конический (угловой) градиент.
  2. Добавьте два или более цветовых перехода с помощью gradient.addColorStop(offset, color).
  3. Присвойте градиент свойству ctx.fillStyle или ctx.strokeStyle.
  4. Нарисуйте фигуру (fillRect, fill, stroke, fillText, …). Градиент применяется везде, где вы рисуете.

Важно понимать: координаты градиента задаются в пространстве canvas (абсолютные), а не относительно заполняемой фигуры. Градиент, созданный от (0, 0) до (300, 0), всегда охватывает именно эту область canvas. Если нарисовать прямоугольник за пределами этого диапазона, он получит первый или последний цвет градиента (ближайший), поскольку цвета до смещения 0 и после смещения 1 фиксируются на граничных значениях.

addColorStop(): расстановка цветов

gradient.addColorStop(offset, color) добавляет одну точку цвета к градиенту.

  • offset — число от 0.0 (начало градиента) до 1.0 (конец). Значения за пределами этого диапазона вызывают ошибку.
  • color — любая CSS-строка цвета: название ("green"), hex ("#14389c"), rgb()/rgba() или hsl(). Используйте альфа-канал (rgba(...)) для прозрачных точек.

Для видимого перехода необходимо не менее двух точек. Смещение каждой точки определяет место перехода — чем меньше расстояние между двумя смещениями, тем резче смена цвета между ними. Равномерное распределение даёт плавный переход; скопление смещений в одном месте создаёт резкие полосы.

<!DOCTYPE html>
<html>
  <head>
    <title>Three color stops</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="stopsCanvas" width="300" height="120"></canvas>
    <script>
      const ctx = document.getElementById("stopsCanvas").getContext("2d");
      const grd = ctx.createLinearGradient(0, 0, 300, 0);
      grd.addColorStop(0, "red");      // start
      grd.addColorStop(0.5, "yellow"); // exact middle
      grd.addColorStop(1, "green");    // end
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 300, 120);
    </script>
  </body>
</html>

Переместите среднюю точку с 0.5 на 0.85 — жёлтая полоса сместится вправо, и большая часть полосы окажется переходом от красного к жёлтому. Именно так смещение управляет положением цвета.

Линейный градиент

ctx.createLinearGradient(x0, y0, x1, y1) возвращает градиент, цвет которого меняется вдоль прямой линии — вектора градиента, идущего от начальной точки (x0, y0) до конечной точки (x1, y1):

  • x0, y0 — начальная точка градиента. Цвет со смещением 0 рисуется здесь.
  • x1, y1 — конечная точка градиента. Цвет со смещением 1 рисуется здесь.

Направление линии между этими двумя точками определяет направление градиента, а расстояние между ними — насколько далеко растягивается переход. Линии, перпендикулярные вектору, имеют единый сплошной цвет.

  • Горизонтальный градиент: y одинаковый: createLinearGradient(0, 0, 300, 0).
  • Вертикальный градиент: x одинаковый: createLinearGradient(0, 0, 0, 200).
  • Диагональный градиент: меняются оба значения: createLinearGradient(0, 0, 300, 200).

Помните про систему координат canvas: (0, 0) — верхний левый угол, x увеличивается вправо, y — вниз.

Пример горизонтального линейного градиента с использованием fillStyle

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      canvas {
        border: 1px solid #cccccc;
      }
    </style>
  </head>
  <body>
    <canvas id="exampleCanvas" width="300" height="150">
      Your browser doesn't support the HTML5 canvas tag.
    </canvas>
    <script>
      var c = document.getElementById("exampleCanvas");
      var ctx = c.getContext("2d");
      var grd = ctx.createLinearGradient(0, 0, 300, 0);
      grd.addColorStop(0, "green");
      grd.addColorStop(1, "whitesmoke");
      ctx.fillStyle = grd;
      ctx.fillRect(20, 20, 260, 110);
    </script>
  </body>
</html>

Поскольку вектор идёт от (0, 0) до (300, 0), переход чисто горизонтальный: левый край зелёный, правый — whitesmoke.

Пример вертикального линейного градиента

Оставьте x одинаковым в обеих точках (здесь 0) и изменяйте только y, чтобы получить переход сверху вниз:

<!DOCTYPE html>
<html>
  <head>
    <title>Vertical gradient</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="verticalCanvas" width="300" height="200"></canvas>
    <script>
      const ctx = document.getElementById("verticalCanvas").getContext("2d");
      // Same x (0), different y → top-to-bottom blend.
      const grd = ctx.createLinearGradient(0, 0, 0, 200);
      grd.addColorStop(0, "#1e3c72"); // top
      grd.addColorStop(1, "#2a5298"); // bottom
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 300, 200);
    </script>
  </body>
</html>

Пример диагонального линейного градиента

Измените и x, и y, чтобы вектор шёл из угла в угол:

<!DOCTYPE html>
<html>
  <head>
    <title>Diagonal gradient</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="diagonalCanvas" width="300" height="200"></canvas>
    <script>
      const ctx = document.getElementById("diagonalCanvas").getContext("2d");
      // Vector from the top-left corner to the bottom-right corner.
      const grd = ctx.createLinearGradient(0, 0, 300, 200);
      grd.addColorStop(0, "#ff512f");
      grd.addColorStop(0.5, "#f09819");
      grd.addColorStop(1, "#ffd452");
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 300, 200);
    </script>
  </body>
</html>

Пример линейного градиента с использованием fillStyle и разными цветами:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      canvas {
        border: 2px solid #202131;
      }
    </style>
  </head>
  <body>
    <canvas id="exampleCanvas" width="500" height="200"></canvas>
    <script>
      var canvas = document.getElementById('exampleCanvas');
      var context = canvas.getContext('2d');
      context.rect(0, 0, 500, 200);
      var linear = context.createLinearGradient(0, 0, 500, 200);
      linear.addColorStop(0, '#297979');
      linear.addColorStop(1, '#2ee035');
      context.fillStyle = linear;
      context.fill();
    </script>
  </body>
</html>

Пример линейного градиента с использованием fillStyle и strokeStyle:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      canvas {
        border: 5px solid #cccccc;
      }
    </style>
    <script>
      function drawShape() {
        var canvas = document.getElementById('canvasGradient');
        if (canvas.getContext) {
          var ctx = canvas.getContext('2d');
          var lgrad1 = ctx.createLinearGradient(0, 0, 0, 300);
          lgrad1.addColorStop(0, 'blue');
          lgrad1.addColorStop(0.4, 'lightpink');
          lgrad1.addColorStop(0.5, 'purple');
          lgrad1.addColorStop(1, 'lightsalmon');
          var lgrad2 = ctx.createLinearGradient(0, 50, 0, 150);
          lgrad2.addColorStop(0, '#7afff3');
          lgrad2.addColorStop(0.5, '#191918');
          lgrad2.addColorStop(1, '#7afff3');
          ctx.fillStyle = lgrad1;
          ctx.strokeStyle = lgrad2;
          ctx.fillRect(15, 15, 120, 120);
          ctx.strokeRect(100, 50, 100, 50);
        } else {
          alert('Your browser does not support');
        }
      }
    </script>
  </head>
  <body onload="drawShape();">
    <canvas id="canvasGradient" width="300" height="300"></canvas>
  </body>
</html>

Пример градиента на тексте и пути

Градиент не ограничивается прямоугольниками — он работает с любой заливкой или обводкой, включая текст и произвольные пути. Задайте его как fillStyle перед fillText() (см. рисование текста на canvas) или перед fill()/stroke() для построенного пути (см. рисование на canvas).

<!DOCTYPE html>
<html>
  <head>
    <title>Gradient text and path</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="textCanvas" width="400" height="160"></canvas>
    <script>
      const ctx = document.getElementById("textCanvas").getContext("2d");

      // A gradient spanning the canvas width.
      const grd = ctx.createLinearGradient(0, 0, 400, 0);
      grd.addColorStop(0, "#8e2de2");
      grd.addColorStop(1, "#4a00e0");

      // Fill text with the gradient.
      ctx.font = "bold 48px sans-serif";
      ctx.fillStyle = grd;
      ctx.fillText("Gradient", 30, 70);

      // Stroke a triangular path with the same gradient.
      ctx.beginPath();
      ctx.moveTo(40, 100);
      ctx.lineTo(360, 100);
      ctx.lineTo(200, 145);
      ctx.closePath();
      ctx.lineWidth = 6;
      ctx.strokeStyle = grd;
      ctx.stroke();
    </script>
  </body>
</html>

Радиальный градиент

ctx.createRadialGradient(x0, y0, r0, x1, y1, r1) определяет градиент между двумя окружностями. Цвет переходит от начальной окружности к конечной:

  • x0, y0, r0 — центр (x0, y0) и радиус r0 начальной (внутренней) окружности. Цвет со смещением 0 заполняет эту окружность.
  • x1, y1, r1 — центр (x1, y1) и радиус r1 конечной (внешней) окружности. Цвет со смещением 1 достигается у края этой окружности.

Когда обе окружности имеют одинаковый центр, получается идеально концентрическое свечение. Когда центр внутренней окружности смещён относительно внешней, яркая точка сдвигается в сторону — именно так имитируется источник освещения или глянцевый блик (в примере ниже используются смещённые центры). Если r0 больше 0, перед началом перехода появляется сплошное ядро первого цвета.

Пример радиального градиента со смещёнными центрами

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      canvas {
        border: 2px solid #cccccc;
      }
    </style>
  </head>
  <body>
    <canvas id="exampleCanvas" width="300" height="150">
      Your browser doesn't support the HTML5 canvas tag.
    </canvas>
    <script>
      var c = document.getElementById("exampleCanvas");
      var ctx = c.getContext("2d");
      var grd = ctx.createRadialGradient(155, 80, 20, 130, 40, 190);
      grd.addColorStop(0, "#14389c");
      grd.addColorStop(1, "white");
      ctx.fillStyle = grd;
      ctx.fillRect(15, 15, 270, 120);
    </script>
  </body>
</html>

Здесь внутренняя окружность центрирована в (155, 80) с радиусом 20, а внешняя — в (130, 40) с радиусом 190. Поскольку центры различаются, тёмно-синее ядро смещено вниз и вправо, а переход к белому происходит асимметрично, создавая объёмный эффект освещения с одной стороны.

Пример радиального свечения

Небольшой полностью прозрачный внешний стоп над прозрачной областью canvas создаёт мягкое свечение, которое можно накладывать поверх других рисунков. Обратите внимание на использование rgba(), чтобы край постепенно исчезал, а не переходил в белый:

<!DOCTYPE html>
<html>
  <head>
    <title>Radial glow</title>
    <style>
      canvas { border: 1px solid #cccccc; background: #11131f; }
    </style>
  </head>
  <body>
    <canvas id="glowCanvas" width="300" height="200"></canvas>
    <script>
      const ctx = document.getElementById("glowCanvas").getContext("2d");
      // Concentric circles: solid core at (150,100), fading out to radius 110.
      const grd = ctx.createRadialGradient(150, 100, 5, 150, 100, 110);
      grd.addColorStop(0, "rgba(255, 214, 102, 1)");   // bright core
      grd.addColorStop(0.4, "rgba(255, 154, 0, 0.6)"); // warm mid
      grd.addColorStop(1, "rgba(255, 154, 0, 0)");     // transparent edge
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 300, 200);
    </script>
  </body>
</html>

Конический градиент

ctx.createConicGradient(startAngle, x, y) создаёт градиент, который разворачивает цвета вокруг центральной точки, как цветовое колесо или круговая диаграмма, а не вдоль линии или между окружностями:

  • startAngle — угол в радианах, с которого начинается смещение 0, отсчитывается по часовой стрелке от положительного направления оси x.
  • x, y — центральная точка вращения.

Точки цвета расставляются вокруг полного оборота, поэтому смещение 0 и смещение 1 встречаются обратно в startAngle. Чтобы избежать видимого шва, задайте первой и последней точке одинаковый цвет.

<!DOCTYPE html>
<html>
  <head>
    <title>Conic gradient</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="conicCanvas" width="200" height="200"></canvas>
    <script>
      const ctx = document.getElementById("conicCanvas").getContext("2d");
      // Sweep starting at the top (-90° = -Math.PI/2), centered at (100,100).
      const grd = ctx.createConicGradient(-Math.PI / 2, 100, 100);
      grd.addColorStop(0, "red");
      grd.addColorStop(0.25, "yellow");
      grd.addColorStop(0.5, "lime");
      grd.addColorStop(0.75, "blue");
      grd.addColorStop(1, "red"); // matches stop 0 → seamless wheel
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 200, 200);
    </script>
  </body>
</html>

createConicGradient() поддерживается в текущих версиях всех основных браузеров (Chrome, Edge, Firefox и Safari). Предусмотрите резервный сплошной цвет для очень старых браузеров, если необходимо их поддерживать.

Практика

Практика
Какие из этих методов используются для применения цветов, шаблонов и градиентов к фигурам на HTML5 canvas?
Какие из этих методов используются для применения цветов, шаблонов и градиентов к фигурам на HTML5 canvas?
Практика
Что представляет аргумент offset в addColorStop(offset, color)?
Что представляет аргумент offset в addColorStop(offset, color)?
Практика
Чтобы линейный градиент переходил строго сверху вниз, как следует задать точки в createLinearGradient(x0, y0, x1, y1)?
Чтобы линейный градиент переходил строго сверху вниз, как следует задать точки в createLinearGradient(x0, y0, x1, y1)?

Связанные главы canvas

Was this page helpful?