Todd Main
Todd Main

Reputation: 29153

How to mask a portion of a stroked path in SVG?

I'm looking to mask a portion of a straight line in SVG and can really only figure out how to do it one way, but would rather do another because the line lengths will be dynamically generated and the mask portion won't.

Let me explain.

Assume I have a line that is <path d="M0,0 L0,100" stroke="blue" stroke-width="20"/>, I would like to mask with transparency the first 10 pixels, meaning just the d="M0,0 L0,10" portion.

I can do this, which produces the results I'd like:

<svg width="100" height="100">
  <rect stroke="black" stroke-width="2" width="100" height="100" fill="yellow"/>
  <svg x="10" y="0" width="200" height="200"  >
    <defs>
      <rect x="0" y="0" width="20" height="10" stroke="none"/>
      <mask id="chopmask" maskUnits="userSpaceOnUse">
        <rect width="20" height="90" x="0" y="10" fill="white"/>
      </mask>
    </defs>
    <path d="M0,0 L0,100" mask="url(#chopmask)" stroke="blue" stroke-width="20"/>
  </svg>
</svg>

But the issue is that I can't seem to do the opposite with the rect in the mask, wherein I simply define the it as <rect width="20" height="10" x="0" y="0" fill="white"/> (notice only height and y are different).

Am I missing something on how do define a 10x20 rectangle and have it's mask simply hide a portion of a stroked path, or is this impossible?

Upvotes: 2

Views: 563

Answers (2)

Michael Mullany
Michael Mullany

Reputation: 31715

Works for me ... am I misunderstanding what you're trying to do?

<svg width="100" height="100">
  <rect stroke="black" stroke-width="2" width="100" height="100" fill="yellow"/>
  <svg x="10" y="0" width="200" height="200"  >
    <defs>
      <rect x="0" y="0" width="20" height="10" stroke="none"/>
      <mask id="chopmask" maskUnits="userSpaceOnUse">
        <rect width="20" height="10" x="0" y="0" fill="white"/>
      </mask>
    </defs>
    <path d="M0,0 L0,100" mask="url(#chopmask)" stroke="blue" stroke-width="20"/>
  </svg>
</svg>

Upvotes: 1

Alexandr_TT
Alexandr_TT

Reputation: 14545

If I understood the question correctly, then you need to have a mask in the form of a rectangle of fixed size 10Х20, which will be applied to the line with variable length.

In this case, you can try on a combined mask, one part of which will be opaque fill = "black" and the second part will be transparent fill = "white" and show the rest of the line.

<svg width="100" height="100">
  <rect stroke="black" stroke-width="2" width="100" height="100" fill="yellow"/>
  <svg x="10" y="0" width="200" height="200"  >
    <defs>
       <mask id="chopmask" maskUnits="userSpaceOnUse">
       <rect width="20" height="100" x="0" y="0" fill="white"/>
         <rect width="20" height="10" x="0" y="0" fill="black"/>
     </mask>
    </defs>
	      <path d="M0,0 L0,100" mask="url(#chopmask)" stroke="blue" stroke-width="20"/>
  </svg> 
</svg>

An example of animating the line masking process with a rectangle 10 x 20px

<svg width="100" height="100">
  <rect stroke="black" stroke-width="2" width="100" height="100" fill="yellow"/>
  <svg x="10" y="0" width="200" height="200"  >
    <defs>
      <rect x="0" y="0" width="20" height="10" stroke="none"/>
      <mask id="chopmask" maskUnits="userSpaceOnUse">
	    <rect width="20" height="100" x="0" y="0" fill="white"/>
         <rect width="20" height="10" x="0" y="0" fill="black">
		    <animate attributeName="y" dur="2s" values="-10;0" fill="freeze" />
		  </rect> 
     </mask>
    </defs>
	      <path d="M0,0 L0,100" mask="url(#chopmask)" stroke="blue" stroke-width="20"/>
  </svg> 
</svg>

Upvotes: 1

Related Questions