Радиальные градиенты SVG - влияние движущейся точки фокусировки (центр)
Сейчас я изучаю SVG и застрял в теме «Радиальные градиенты», в разделе о точном перемещении центра радиального градиента.
Скажем, у меня есть 2 примера градиента (фрагмент кода, чтобы поиграть). Базовый (отлично работает):
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en"xmlns:xlink="http://www.w3.org/1999/xlink"width="200px" height="200px" viewBox="0 0 200 200">
<title>Bulls-eye Repeating Radial Gradient</title>
<radialGradient id="bullseye"cx="50%" cy="50%" r="10%" spreadMethod="repeat">
<stop stop-color="tomato" offset="50%"/>
<stop stop-color="#222" offset="50%"/>
</radialGradient>
<rect width="100%" height="100%" rx="10%"fill="url(#bullseye)"/>
</svg>
и пример, в котором я пытаюсь применить атрибуты fx и fy для перемещения фокальной точки градиента:
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en"xmlns:xlink="http://www.w3.org/1999/xlink"width="200px" height="200px" viewBox="0 0 200 200">
<title>Bulls-eye Repeating Radial Gradient</title>
<radialGradient id="bullseye2" cx="50%" cy="50%" r="10%" fx=".2" fy=".2" spreadMethod="repeat">
<stop stop-color="tomato" offset="50%"/>
<stop stop-color="#222" offset="50%"/>
</radialGradient>
<rect width="100%" height="100%" rx="10%"fill="url(#bullseye2)"/>
</svg>
Здесь он каким-то образом просто вырезал кусок формы, а не просто перемещал центральную точку.
Не могли бы вы объяснить, что я здесь делаю не так и почему это работает так странно?
Свободный перевод вопроса SVG radial gradients - moving focal point (center) от участника @Natalia Davydova.
Ответы (1 шт):
При определении радиального градиента используются две основные концепции:
- Точка, где начинается градиент (
focal point) - Эллипс, определяющий "внешнюю" форму градиента.
Я упомяну опцию repeat позже, а пока: градиент рендерится от центральной точки наружу, пока не достигнет внешнего края формы. Может быть, будет полезно представить, как внешняя форма сжимается, пока не достигнет фокальной точки.
Это означает, что если точка фокусировки находится внутри определенной формы, она будет казаться довольно интуитивной:
<svg viewBox="0 0 120 120" width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="Gradient" cx="0.5" cy="0.5" r="0.5"
fx="0.35" fy="0.35">
<stop offset="0%" stop-color="red"/>
<stop offset="100%" stop-color="blue"/>
</radialGradient>
</defs>
<rect x="10" y="10" width="100" height="100"
fill="url(#Gradient)" />
<circle cx="60" cy="60" r="50" fill="transparent" stroke="white" stroke-width="1"/>
<circle cx="45" cy="45" r="2" fill="white" stroke="white"/>
<circle cx="60" cy="60" r="2" fill="white" stroke="white"/>
<text x="38" y="40" fill="white" font-family="sans-serif" font-size="10pt">(fx,fy)</text>
<text x="63" y="63" fill="white" font-family="sans-serif" font-size="10pt">(cx,cy)</text>
</svg>
пример взят из MDN, немного исправлен и изменен)
Однако, если точка фокусировки находится за пределами ограничивающей формы, то вы получите нечто большее, чем конус:
<svg viewBox="0 0 120 120" width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="Gradient" cx="0.5" cy="0.5" r="0.5"
fx="0.05" fy="0.05">
<stop offset="0%" stop-color="red"/>
<stop offset="100%" stop-color="blue"/>
</radialGradient>
</defs>
<rect x="10" y="10" width="100" height="100"
fill="url(#Gradient)" />
<circle cx="60" cy="60" r="50" fill="transparent" stroke="white" stroke-width="1"/>
<circle cx="15" cy="15" r="2" fill="white" stroke="white"/>
<circle cx="60" cy="60" r="2" fill="white" stroke="white"/>
<text x="28" y="30" fill="white" font-family="sans-serif" font-size="10pt">(fx,fy)</text>
<text x="63" y="63" fill="white" font-family="sans-serif" font-size="10pt">(cx,cy)</text>
</svg>
Обратите внимание, что он по-прежнему берет круг и «сжимает» его по направлению к фокусной точке, но поскольку фокус теперь находится за пределами круга, он не может определить какой-либо значимый цвет для точек за пределами конуса.
Вы перемещаете фокус с помощью fx и fy. Также есть fr, который иногда бывает полезен, но пока не обращайте на него внимания; в любом случае вы можете сделать то же самое с цветными стоп-позициями.
Также Вы можете перемещать круг с помощью cx, cy и r.
Перемещение обоих атрибутов приводит просто к перемещению градиента.
Repeat делает это немного более запутанным, но, возможно, эта демонстрация прояснит:
<svg viewBox="0 0 120 120" width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="Gradient" cx="0.5" cy="0.5" r="0.3"
fx="0.4" fy="0.4" spreadMethod="repeat">
<stop offset="0%" stop-color="red"/>
<stop offset="100%" stop-color="blue"/>
</radialGradient>
</defs>
<rect x="10" y="10" width="100" height="100"
fill="url(#Gradient)" />
<circle cx="60" cy="60" r="30" fill="transparent" stroke="white" stroke-width="1"/>
<circle cx="50" cy="50" r="2" fill="white" stroke="white"/>
<circle cx="60" cy="60" r="2" fill="white" stroke="white"/>
<text x="38" y="40" fill="white" font-family="sans-serif" font-size="10pt">(fx,fy)</text>
<text x="63" y="63" fill="white" font-family="sans-serif" font-size="10pt">(cx,cy)</text>
</svg>
Белый круг по-прежнему определяет форму, поэтому для интуитивно понятного результата точка фокусировки должна находиться внутри него.
В опубликованном вами примере градиент очень маленький; занимая всего 10 пикселей вокруг центра. Он определяет переход одного цвета. Эффект полосатости обусловлен опцией повтора. Вот ваш пример с проиллюстрированным фокусом и внешней формой:
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en"xmlns:xlink="http://www.w3.org/1999/xlink"width="200px" height="200px" viewBox="0 0 200 200">
<title>Bulls-eye Repeating Radial Gradient</title>
<radialGradient id="bullseye"cx="50%" cy="50%" r="10%" spreadMethod="repeat">
<stop stop-color="tomato" offset="50%"/>
<stop stop-color="#222" offset="50%"/>
</radialGradient>
<rect width="100%" height="100%" fill="url(#bullseye)"/>
<circle cx="50%" cy="50%" r="10%" fill="transparent" stroke="white" stroke-width="1"/>
<circle cx="50%" cy="50%" r="2" fill="white" stroke="white"/>
</svg>
и вот ваш второй пример (на этот раз точка фокусировки для ясности показана черным):
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en"xmlns:xlink="http://www.w3.org/1999/xlink"width="200px" height="200px" viewBox="0 0 200 200">
<title>Bulls-eye Repeating Radial Gradient</title>
<radialGradient id="bullseye"cx="50%" cy="50%" fx=".2" fy=".2" r="10%" spreadMethod="repeat">
<stop stop-color="tomato" offset="50%"/>
<stop stop-color="#222" offset="50%"/>
</radialGradient>
<rect width="100%" height="100%" fill="url(#bullseye)"/>
<circle cx="50%" cy="50%" r="10%" fill="transparent" stroke="white" stroke-width="1"/>
<circle cx="20%" cy="20%" r="2" fill="black" stroke="black"/>
</svg>