Search code examples
htmlsvgpathtransparency

Overlapping a colored rect with transparent path in a svg / breaking rect fill color on the intersection with a path


I have a similar code to the following, generated by a dynamic content creation tool i.e. the user of the tool will choose the colors as he wants. The problem appears when the rect is colored but the inside of the path is transparent, so the color of the rect will fill all the part inside the path. The goal is to show the rect colored as it should be but avoid coloring the internal part of the path when it is transparent and instead a potential object behind this transparent part can be shown.

    <svg xmlns="http://www.w3.org/2000/svg"  style="position: absolute;" id="id2_svg" >
    <g id="id2_g" >
    <rect id="id2_rect" style="fill:rgba(255 , 255 , 0 , 255);"  />
    <path id="id2_path" d="M 32.0 2.0 C 6.0 -2.0 -10.0 71.0 13.0 89.0 C 36.0 107.0 168.0 125.0 171.0 111.0 C 174.0 96.0 58.0 6.0 32.0 2.0" style=  "fill: #fff; fill-opacity: 0;  pointer-events: visiblePainted" />
    </g>
    </svg>

Any use of fill values in the path style will give the same result. Using stroke can keep the inside of the path determined but with a black background!


Solution

  • The OP is adding this comment:

    Is there any way to break the fill of the rect in the intersection with the path?

    You may clip the rect like so:

       <svg viewBox="0 0 300 150" >
        <defs>
          <clipPath id="clip">
          <path id="id2_path" d="M 32.0 2.0 C 6.0 -2.0 -10.0 71.0 13.0 89.0 C 36.0 107.0 168.0 125.0 171.0 111.0 C 174.0 96.0 58.0 6.0 32.0 2.0"  />
          </clipPath>
        </defs>
        <g id="id2_g" >
        <rect id="id2_rect" style="fill:rgba(255 , 255 , 0 , 255);" width="100" height="100" clip-path="url(#clip)" />
        <use xlink:href="#id2_path" stroke="black" fill="none"/>
        </g>
        </svg>

    The OP is commenting:

    Actually what I want is the inverse of this. By using clip path, I clip the outside of the path i.e. like making it transparent but what I want is to clip inside the path and make it transparent while keeping the color of the rest of the rectangle as it is. Anyway thanks for your answer !

    In this case I suggest using a modified path. To the original d attribute I would add this: M0,0H300V150H0V0z. I hope this is what you need.

      <svg viewBox="0 0 300 150" >
        <defs>
          <clipPath id="clip">
          <path id="id2_path" d="M 32.0 2.0 C 6.0 -2.0 -10.0 71.0 13.0 89.0 C 36.0 107.0 168.0 125.0 171.0 111.0 C 174.0 96.0 58.0 6.0 32.0 2.0
          M0,0H300V150H0V0z"  />
          </clipPath>
        </defs>
        <g id="id2_g" >
        <rect id="id2_rect" style="fill:rgba(255 , 255 , 0 , 255);" width="100" height="100" clip-path="url(#clip)" />
        <path id="id2_path" d="M 32.0 2.0 C 6.0 -2.0 -10.0 71.0 13.0 89.0 C 36.0 107.0 168.0 125.0 171.0 111.0 C 174.0 96.0 58.0 6.0 32.0 2.0" stroke="black" fill="none" />
        </g>
        </svg>

    UPDATE:

    This should help me but can you explain in details why you have added this to the original path

    By adding M0,0H300V150H0V0z to the path you draw a rectangle as big as the svg canvas The rectangle is drawn in the opposite sense. In this case you draw the path from left to right and the added rectangle from right to left. this way you create a rectangle with a hole and you are using this shape for the clipPath:

    The miming of the added string: M0,0H300V150H0V0z

    • move to the origin of the svg canvas M0,0

    • horizontal line from previous point to the point {300,0} H300

    • vertical line from previous point to the point {300,150} V150

    • horizontal line from previous point to the point {0,150} H0

    • vertical line from previous point to the point {0,0} V0

    • close path: z

    <svg viewBox="0 0 300 150" >
    <path id="id2_path" d="M 32.0 2.0 C 6.0 -2.0 -10.0 71.0 13.0 89.0 C 36.0 107.0 168.0 125.0 171.0 111.0 C 174.0 96.0 58.0 6.0 32.0 2.0  M0,0H300V150H0V0z"  />
    </svg>

    And why you added again the original path points inside the <g> tag.

    Because now the path used for the clipPath looks different with the added string.