Можно ли преобразовать рейдовый градиент, выраженный в координатах objectBoundingBox, в координаты userSpaceOnUse? - PullRequest
1 голос
/ 09 июля 2020

У меня этот радиальный градиент выражен в координатах objectBoundingBox.

<svg width="300" height="300">
  <defs>
    <radialGradient id="MyGradient" gradientUnits="objectBoundingBox"
                    cx="0.3" cy="0.4" r="0.3" fx="0.1" fy="0.2">
      <stop offset="0%" stop-color="red" />
      <stop offset="50%" stop-color="blue" />
      <stop offset="100%" stop-color="black" />
    </radialGradient>
  </defs>

  <rect fill="url(#MyGradient)" stroke="black" stroke-width="5"  
        x="50" y="100" width="200" height="100"/>
</svg>

Можно ли преобразовать его в координаты userSpaceOnUse?

Для этого вопроса то же самое, если предположить, что каждый радиальный градиент применимо только к одной форме, и мы знаем x, y, ширину и высоту указанной формы.

<svg width="300" height="300">
  <defs>
    <radialGradient id="MyGradient" gradientUnits="userSpaceOnUse"
                    cx="?" cy="?" r="?" fx="?" fy="?">
      <stop offset="0%" stop-color="red" />
      <stop offset="50%" stop-color="blue" />
      <stop offset="100%" stop-color="black" />
    </radialGradient>
  </defs>

  <rect fill="url(#MyGradient)" stroke="black" stroke-width="5"  
        x="50" y="100" width="200" height="100"/>
</svg>

1 Ответ

2 голосов
/ 09 июля 2020

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

svg{border:solid; width:45vw}
<svg viewBox="0 0 300 300">
  <defs>
    <radialGradient id="MyGradient" gradientUnits="objectBoundingBox"
                    cx="0.3" cy="0.4" r="0.3" fx="0.1" fy="0.2">
      <stop offset="0%" stop-color="red" />
      <stop offset="50%" stop-color="blue" />
      <stop offset="100%" stop-color="black" />
    </radialGradient>
  </defs>

  <rect fill="url(#MyGradient)" stroke="black" stroke-width="5"  
        x="50" y="100" width="200" height="200"/>
</svg>

<svg viewBox="0 0 300 300">
  <defs>
    <radialGradient id="MyGradient1" gradientUnits="userSpaceOnUse"
                    cx="110" cy="180" r="60" fx="70" fy="140" >
      <stop offset="0%" stop-color="red" />
      <stop offset="50%" stop-color="blue" />
      <stop offset="100%" stop-color="black" />
    </radialGradient>
  </defs>

  <rect fill="url(#MyGradient1)" stroke="black" stroke-width="5"  
        x="50" y="100" width="200" height="200"/>
</svg>

В случае gradientUnits = "userSpaceOnUse":

Ограничивающая рамка прямоугольника для заливки:

bb:{x:50, y:100, width:200, height:200}

Вычисленные атрибуты для gradientUnits="userSpaceOnUse":

cx = bb.x + bb.width *.3 = 50 + 200 * .3 = 110
cy = bb.y + bb.height *.4 100 + 200*.4 = 180
r = bb.width*.3 = 200*.3 = 60
fx = bb.x + bb.width *.1 = 50 + 200 * .1 = 70
fy = bb.y + bb.height *.2 = 100 + 200 * .2 = 140

Таким образом, вы можете использовать

<radialGradient id="MyGradient1" gradientUnits="userSpaceOnUse" cx="110" cy="180" r="60" fx="70" fy="140" >

При использовании objectBoundingBox значения атрибутов radialGradient принимают значения от 0 до 1 или от 0 до 100% от заполненного поля.

Вы также можете использовать objectBoundingBox как значение для clipPathUnits. Взгляните на следующий пример.

Это clipPath, где контур обрезки представляет собой круг. Если обрезанная форма представляет собой квадрат, результатом будет круг. Если обрезанная форма представляет собой прямоугольник, результатом является эллипс, означающий, что путь обрезки растягивается в соответствии с соотношением сторон обрезанной формы.

<svg viewBox="0 0 120 60"> 
  <defs>
  <clipPath id="clip" clipPathUnits="objectBoundingBox">
    <circle cx=".5" cy=".5" r=".45" />
  </clipPath> 
  </defs>
    <rect id="r"  x="5" y="5" width="50"  height="50" />
  <use xlink:href="#r" fill="gold" clip-path="url(#clip)" />
  
  <rect id="r1"  x="60" y="15" width="55"  height="30" />
  <use xlink:href="#r1" fill="gold" clip-path="url(#clip)" />
</svg>

То же самое происходит с градиентом. Если радиальный градиент с gradientUnits="objectBoundingBox" используется для заливки прямоугольника с другой шириной и высотой, результатом будет эллиптический градиент (как в вашем примере). Если вы хотите преобразовать эллиптический градиент в gradientUnits="userSpaceOnUse", вам понадобится способ создать градиент с другим rx и ry. К сожалению, это невозможно .

...