Home > OS >  SVG textPath with linear gradient is damaged in Safari
SVG textPath with linear gradient is damaged in Safari

Time:10-06

The textPath is damaged when I fill linear gradient. How to fix it? Thanks.

[[the broken image]]: https://i.stack.imgur.com/200t3.png

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" width="1000" height="1000">
  <g font-size="42.5" font-weight="800">
<path d="M 400, 400
      m -100, 0
      a 100, 100 0 1,0 200, 0
      a 100, 100 0 1,0 -200, 0" fill="transparent" stroke="black" id="SvgjsPath1000"></path>
<circle r="4" cx="400" cy="400" fill="#000000"></circle>
<text stroke-width="10" svgjs:data="{&quot;leading&quot;:&quot;1.3&quot;}">
  <textPath xlink:href="#SvgjsPath1000" fill="transparent" stroke="#ffffff" svgjs:data="{&quot;leading&quot;:&quot;1.3&quot;}">
    <tspan alignment-baseline="middle">RRRRRRRRRRRRRRRRRRRRR</tspan>
  </textPath>
</text>
<text svgjs:data="{&quot;leading&quot;:&quot;1.3&quot;}">
  <textPath xlink:href="#SvgjsPath1000" fill="url(&quot;#SvgjsLinearGradient1001&quot;)" svgjs:data="{&quot;leading&quot;:&quot;1.3&quot;}">
    <tspan alignment-baseline="middle">RRRRRRRRRRRRRRRRRRRRR</tspan>
  </textPath>
</text>
  </g>
  <defs>
<linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="SvgjsLinearGradient1001">
  <stop offset="0" style="stop-color:#007cf0"></stop>
  <stop offset="1" style="stop-color:#ff0080"></stop>
</linearGradient>
  </defs>
</svg>

CodePudding user response:

Apparently, a safari specific rendering bug when applying gradients to <textPath> elements.

I could also reproduce this issue with a simplified example (testing in iOS safari):

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="myGradient" gradientTransform="rotate(90)">
      <stop offset="5%" stop-color="gold" />
      <stop offset="95%" stop-color="red" />
    </linearGradient>  
  </defs>
  <path
    id="MyPath"
    fill="none"
    stroke="red"
    d="M10,90 Q90,90 90,45 Q90,10 50,10 Q10,10 10,40 Q10,70 45,70 Q70,70 75,50" />
  <text>
    <textPath fill="url('#myGradient')" href="#MyPath">Quick brown fox jumps over the lazy dog.</textPath>
  </text>
</svg>

Workaround: create a <mask> containing the text path:

body {
  background: #ccc
}

svg {
  width: 50%;
  border: 1px solid #000
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" viewBox="250 250 300 300">
  <defs>
    <linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="SvgjsLinearGradient1001">
      <stop offset="0" style="stop-color:#007cf0"></stop>
      <stop offset="1" style="stop-color:#ff0080"></stop>
    </linearGradient>
    <mask id="mask" x="0" y="0" width="200%" height="200%">
      <rect fill="#000" x="0" y="0" width="200%" height="200%" />
      <text>
        <textPath  font-size="42.5" font-weight="800" href="#SvgjsPath1000" dominant-baseline="middle" fill="#fff">
          RRRRRRRRRRRRRRRRRRRRR
        </textPath>
      </text>
    </mask>
  </defs>
  <g>
    <path d="M 300 400 a 100 100 0 1 0 200 0 a 100 100 0 1 0 -200 0 z" fill="transparent" stroke="black" id="SvgjsPath1000" />
    <circle r="4" cx="400" cy="400" fill="#000000" />
    <text>
      <textPath  font-size="42.5" font-weight="800" href="#SvgjsPath1000" dominant-baseline="middle" fill="transparent" stroke="#fff" stroke-width="10">
        RRRRRRRRRRRRRRRRRRRRR
      </textPath>
    </text>
    <rect mask="url(#mask)" fill="url(#SvgjsLinearGradient1001)" x="0" y="0" width="200%" height="200%" />
  </g>
</svg>

  • Related