Градиенты в SVG: linearGradient и radialGradient

SVG предоставляет встроенный механизм плавных переходов между цветами через элементы linearGradient и radialGradient, которые размещаются внутри блока <defs> и затем применяются к формам через ссылки `url(

Базовая структура градиентов в SVG

Любой градиент в SVG объявляется внутри контейнера <defs>, который не отображается напрямую, а служит хранилищем ресурсов:

<svg width="400" height="200">
  <defs>
    <!-- градиенты определяются здесь -->
  </defs>
</svg>

Два основных типа градиентов:

  • linearGradient — линейный переход цвета вдоль оси
  • radialGradient — радиальный переход от центра к краям

Линейный градиент (linearGradient)

Линейный градиент задаёт переход цветов вдоль прямой линии. Основные параметры:

  • x1, y1 — начало градиента
  • x2, y2 — конец градиента
  • gradientUnits — система координат (objectBoundingBox или userSpaceOnUse)

Простейшее определение:

<defs>
  <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0%" stop-color="#4facfe" />
    <stop offset="100%" stop-color="#00f2fe" />
  </linearGradient>
</defs>

Применение к фигуре:

<rect x="20" y="20" width="200" height="100" fill="url(#grad1)" />

Управление остановками цвета

Каждый <stop> задаёт точку перехода:

  • offset — положение в процентах или долях (0–1)
  • stop-color — цвет
  • stop-opacity — прозрачность

Пример с прозрачностью:

<linearGradient id="fade">
  <stop offset="0%" stop-color="black" stop-opacity="1" />
  <stop offset="100%" stop-color="black" stop-opacity="0" />
</linearGradient>

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

Радиальный градиент распространяется из центра наружу, формируя эффект свечения или объёма.

Основные параметры:

  • cx, cy — центр
  • r — радиус
  • fx, fy — фокусная точка (смещение центра освещения)
<defs>
  <radialGradient id="grad2" cx="50%" cy="50%" r="50%">
    <stop offset="0%" stop-color="#ff9a9e" />
    <stop offset="100%" stop-color="#fad0c4" />
  </radialGradient>
</defs>

Применение:

<circle cx="100" cy="100" r="80" fill="url(#grad2)" />

Смещение фокуса

Сдвиг fx и fy создаёт эффект направленного освещения:

<radialGradient id="highlight" cx="50%" cy="50%" r="50%" fx="30%" fy="30%">
  <stop offset="0%" stop-color="white" />
  <stop offset="100%" stop-color="#3a3a3a" />
</radialGradient>

Создание градиентов через D3.js

D3.js позволяет генерировать градиенты динамически, что особенно полезно при визуализации данных.

Добавление <defs> через D3

const svg = d3.select("svg");

const defs = svg.append("defs");

Генерация linearGradient в D3.js

Создание линейного градиента программно:

const linearGradient = defs
  .append("linearGradient")
  .attr("id", "linear1")
  .attr("x1", "0%")
  .attr("y1", "0%")
  .attr("x2", "100%")
  .attr("y2", "0%");

Добавление цветовых стопов:

linearGradient
  .selectAll("stop")
  .data([
    { offset: "0%", color: "#4facfe" },
    { offset: "100%", color: "#00f2fe" }
  ])
  .enter()
  .append("stop")
  .attr("offset", d => d.offset)
  .attr("stop-color", d => d.color);

Использование:

svg.append("rect")
  .attr("x", 20)
  .attr("y", 20)
  .attr("width", 200)
  .attr("height", 100)
  .attr("fill", "url(#linear1)");

Генерация radialGradient в D3.js

const radialGradient = defs
  .append("radialGradient")
  .attr("id", "radial1")
  .attr("cx", "50%")
  .attr("cy", "50%")
  .attr("r", "50%");

Добавление стопов:

radialGradient
  .selectAll("stop")
  .data([
    { offset: "0%", color: "#ff9a9e" },
    { offset: "100%", color: "#fad0c4" }
  ])
  .enter()
  .append("stop")
  .attr("offset", d => d.offset)
  .attr("stop-color", d => d.color);

Применение:

svg.append("circle")
  .attr("cx", 120)
  .attr("cy", 120)
  .attr("r", 80)
  .attr("fill", "url(#radial1)");

Динамическое связывание градиентов с данными

Градиенты часто используют для кодирования значений. Например, интенсивность цвета может зависеть от величины данных:

const data = [10, 40, 80, 120];

const colorScale = d3.scaleLinear()
  .domain([0, 120])
  .range(["#dbeafe", "#1e3a8a"]);

Создание нескольких градиентов:

const grads = defs.selectAll("linearGradient")
  .data(data)
  .enter()
  .append("linearGradient")
  .attr("id", (d, i) => `grad-${i}`)
  .attr("x1", "0%")
  .attr("y1", "0%")
  .attr("x2", "0%")
  .attr("y2", "100%");
grads.append("stop")
  .attr("offset", "0%")
  .attr("stop-color", d => colorScale(d))
  .attr("stop-opacity", 1);

grads.append("stop")
  .attr("offset", "100%")
  .attr("stop-color", "#ffffff")
  .attr("stop-opacity", 0.2);

Использование gradientUnits

Поведение градиента зависит от системы координат:

  • objectBoundingBox — относительные координаты (по умолчанию)
  • userSpaceOnUse — абсолютные координаты SVG

Пример фиксированного градиента:

defs.append("linearGradient")
  .attr("id", "fixedGrad")
  .attr("gradientUnits", "userSpaceOnUse")
  .attr("x1", 0)
  .attr("y1", 0)
  .attr("x2", 300)
  .attr("y2", 0);

Такой градиент не масштабируется вместе с объектом.


Анимация градиентов

D3 позволяет изменять свойства stop-элементов для создания анимации переходов.

d3.select("#grad1 stop:first-child")
  .transition()
  .duration(1000)
  .attr("stop-color", "#ff0000");

Также можно анимировать смещение:

d3.selectAll("#grad1 stop")
  .transition()
  .duration(1500)
  .attr("offset", "100%");

Комбинирование нескольких остановок цвета

Градиенты могут содержать множество переходов, создавая сложные визуальные эффекты:

<linearGradient id="multi">
  <stop offset="0%" stop-color="#ff9a9e" />
  <stop offset="30%" stop-color="#fad0c4" />
  <stop offset="60%" stop-color="#fbc2eb" />
  <stop offset="100%" stop-color="#a18cd1" />
</linearGradient>

Практическое применение в визуализациях

Градиенты часто используются в:

  • тепловых картах
  • диаграммах плотности
  • визуализации сетевых графов
  • оформлении столбчатых диаграмм
  • создании объёмного эффекта у кругов и областей

Пример применения к столбчатой диаграмме:

svg.selectAll("rect")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", (d, i) => i * 40)
  .attr("y", d => 200 - d)
  .attr("width", 30)
  .attr("height", d => d)
  .attr("fill", (d, i) => `url(#grad-${i})`);

Особенности отрисовки и производительности

SVG-градиенты рендерятся на уровне графического движка браузера, что делает их:

  • более производительными, чем имитация градиента через множество элементов
  • устойчивыми к масштабированию
  • независимыми от разрешения

При большом количестве элементов стоит избегать чрезмерного дублирования <defs> и использовать переиспользуемые идентификаторы.