jantimon
jantimon

Reputation: 38150

SVG Mask Path is cropped

I am trying to build a javascript experiment of a dynamic chain which follows the mouse cursor.

Therefore I am useing a SVG wwith the following path:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 240">
  <defs>
    <path id="a" d="M143 158q-31-139 9-99" fill="none" stroke-linecap="round"/>
    <mask id="b">
      <rect x="0%" y="0%" width="100%" height="100%" fill="#fff"/>
      <use href="#a" stroke-width="4" stroke-dasharray="6 14" stroke-dashoffset="7" stroke="#000"/>
    </mask>
  </defs>
  <use href="#a" stroke-width="8" stroke-dasharray="6 14" stroke-dashoffset="7" stroke="#333" stroke-opacity=".8" mask="url(#b)"/>
  <use href="#a" stroke-width="2" stroke-dasharray="12 8" stroke="#333" stroke-opacity=".8"/>
</svg>

Unfortunately the chain is cropped:

SVG Chain with crop

Why is this happening?

You can see the full experiment here (desktop only).

Animated Preview of the problem

Upvotes: 4

Views: 212

Answers (2)

Sphinxxx
Sphinxxx

Reputation: 13017

Long story short: A mask works within an object's bounding box, but the bounding box of any element doesn't include the stroke width.

Therefore, the default mask adds 10% padding around the bounding box with its x, y, width, height and maskUnits attributes. This works in most cases, but fails when an element is slim and almost horizontal or vertical.

See the below image: The blue rectangle is your path's bounding box, and the green is the area where the mask does its job. You can see that some of the path sticks out to the left and right.

SVG mask area

So you must change the mask attributes to work for you. For example, make it cover the whole image:

<mask id="b" maskUnits="userSpaceOnUse" x="0" y="0" width="100%" height="100%">

Upvotes: 2

I fixed it by adding maskUnits="userSpaceOnUse"

https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/maskUnits

(changed the viewBox to better display it in an SO snippet)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 40 300 240">
  <defs>
    <path id="a" d="M143 158q-31-139 9-99" fill="none" stroke-linecap="round"/>
    <mask id="b"  maskUnits="userSpaceOnUse">
      <rect x="0%" y="0%" width="100%" height="100%" fill="#fff"/>
      <use href="#a" stroke-width="4" stroke-dasharray="6 14" stroke-dashoffset="7" stroke="#000"/>
    </mask>
  </defs>
  <use href="#a" stroke-width="8" stroke-dasharray="6 14" stroke-dashoffset="7" stroke="#333" stroke-opacity=".8" mask="url(#b)"/>
  <use href="#a" stroke-width="2" stroke-dasharray="12 8" stroke="#333" stroke-opacity=".8"/>
</svg>

Upvotes: 1

Related Questions