Линия SVG с градиентным штрихом не будет отображаться прямо

Я пытаюсь реплицировать <hr> с помощью SVG. Теперь, когда прямая линия с SVG работает отлично, но вторая я поглажу ее градиентом, он больше не будет отображаться по прямой.

Следующий код работает, но обратите внимание: y1 и y2 должны быть разделены на 1 единицу. Если, например, я устанавливаю y1 и y2 - 210, линия исчезнет.

<defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop offset="0%" style="stop-color:rgba(0,0,0,0);stop-opacity:0" />
        <stop offset="50%" style="stop-color:rgba(0,0,0,0.75);stop-opacity:1" />
        <stop offset="100%" style="stop-color:rgba(0,0,0,0);stop-opacity:0" />
    </linearGradient>
</defs>
<line x1="40" y1="210" x2="460" y2="211" stroke="url(#grad1)" stroke-width="1" />

Вероятно, я просто пропустил какую-то очевидную функцию линейных градиентов, и линия выглядит хорошо, но я бы предпочел просто прямолинейно. Спасибо.

Ответ 1

Вы попадаете в последний абзац в этой части спецификации SVG

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

objectBoundingBox по умолчанию используется для gradientUnits, поэтому вам нужно использовать gradientUnits = "userSpaceOnUse", а затем настроить значения, подходящие для разных систем координат.

Ответ 2

Роберт Лонгсон дает отличное объяснение. Но иногда userSpaceOnUse является болью, потому что она распространяет интерполяцию по всему холсту, а не только на строку.

Вместо этого вы можете добавить небольшое количество значений, чтобы гарантировать, что размер bbox не равен нулю.

Например,

  <line x1="40" y1="210" x2="460" y2="210.001" stroke="url(#grad1)" stroke-width="1" />

будет рисовать прямую линию с градиентом.

Ответ 3

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

<path d='M 40 209.5 L 460 209.5 L 460 210.5 L 40 210.5' fill='url(#grad1)' />

или, альтернативно, заполненному прямоугольнику, как показано ниже

<rect x=40 y=209.5 width=420 height=1 fill='url(#grad1)' />

Также интересно отметить, что эта проблема затрагивает только вертикальные и горизонтальные линии. Наклонная линия отображается правильно.