Apply clipPath to transformed g element
Asked Answered
svg
F

1

15

I'm trying to clip a circle so that it only shows for the part that falls within certain bounds. However, the circle is within a g element that is transformed. When I apply the clip path to either the g element or the path within this element ("g.site" or "g.site path") the circle complete gets clipped off. Short example showing my problem:

<svg width="600" height="600">
  <defs>
    <clipPath id="myClip">
      <path d="M435.1256860398758,144.76407538624122L419.76193083948306,273.83328117717105L469.9933509829825,301.0396981292212L483.3234271019269,296.67464757752555L535.23683445551,247.72472220603692L574.3496211247055,127.3184557867296Z"
      />
    </clipPath>
  </defs>
  <g id="voronoi">
    <g id="cells">
      <path class="cell" d="M435.1256860398758,144.76407538624122L419.76193083948306,273.83328117717105L469.9933509829825,301.0396981292212L483.3234271019269,296.67464757752555L535.23683445551,247.72472220603692L574.3496211247055,127.3184557867296Z"
      />
    </g>
    <g id="sites">
      <g class="site" transform="translate(483.29548177370367,267.14072835257724)" clip-path="url(#myClip)">
        <path fill="rgba(0, 255, 0, 0.5)" d="M0,30A30,20 0 1,1 0,-30A30,20 0 1,1 0,30M0,1A1,1 0 1,0 0,-1A1,1 0 1,0 0,1Z"
        />
      </g>
      <g class="site" transform="translate(483.29548177370367,267.14072835257724)">
        <path fill="rgba(0, 0, 255, 0.5)" d="M0,30A30,20 0 1,1 0,-30A30,20 0 1,1 0,30M0,1A1,1 0 1,0 0,-1A1,1 0 1,0 0,1Z"
        />
      </g>
    </g>
  </g>
</svg>

A working demo of my problem can be found in this fiddle: http://jsfiddle.net/xRh6A/

I added two circles. The first one is clipped off (because the clip-path attribute is set), the second is shown but (obviously) not clipped.

I suppose this is related to the fact that the clip-path is defined in absolute terms while the circle element has local coordinates and is then transformed. Can I use the clipPath with a transformed group or do I have to either change the clip path or the circle path in order to make them match?

Edit I solved it by placing the "sites" with absolute coordinates. However, this meant that I couldn't use d3.svg.arc (which is generating the code in the simplified example I attached) because it creates arcs in a local coordinate system.

I'd still be interested to see if it could be solved otherwise as well.

Frendel answered 22/1, 2013 at 10:49 Comment(0)
L
20

Your translation on the g element is affecting how the clipPath is rendered. You have 2 options:

  1. Add the clip-path attribute to a static parent element. You can then apply your translation on the child element without it affecting the clipPath rendering.

  2. Apply the inverse translation on the clipPath element. I've never implemented this method, but I read about it here: https://mcmap.net/q/824314/-clip-path-and-translate-in-quot-g-quot-tag-svg. This option requires that you update the clipPath tranform each time you change the g transform.

In your case, you already have a parent g element so you can add the clip-path attribute there, if you intend to apply the clipPath to every element in your g#sites element.

<g id="sites" clip-path="url(#myClip)">
  <g class="site" transform="translate(483.29548177370367,267.14072835257724)">
    <path fill="rgba(0, 255, 0, 0.5)" d="M0,30A30,20 0 1,1 0,-30A30,20 0 1,1 0,30M0,1A1,1 0 1,0 0,-1A1,1 0 1,0 0,1Z" />
  </g>
  <g class="site" transform="translate(483.29548177370367,267.14072835257724)">
    <path fill="rgba(0, 0, 255, 0.5)" d="M0,30A30,20 0 1,1 0,-30A30,20 0 1,1 0,30M0,1A1,1 0 1,0 0,-1A1,1 0 1,0 0,1Z" />
  </g>
</g>

(jsfiddle: http://jsfiddle.net/SWyeD/)

If you only intend for that clipPath to be applied to the first circle, you'd just add an intermediate container element.

<g id="sites">
  <g clip-path="url(#myClip)">
    <g class="site" transform="translate(483.29548177370367,267.14072835257724)">
      <path fill="rgba(0, 255, 0, 0.5)" d="M0,30A30,20 0 1,1 0,-30A30,20 0 1,1 0,30M0,1A1,1 0 1,0 0,-1A1,1 0 1,0 0,1Z" />
    </g>
  </g>
  <g class="site" transform="translate(483.29548177370367,267.14072835257724)">
    <path fill="rgba(0, 0, 255, 0.5)" d="M0,30A30,20 0 1,1 0,-30A30,20 0 1,1 0,30M0,1A1,1 0 1,0 0,-1A1,1 0 1,0 0,1Z" />
  </g>
</g>

(jsfiddle: http://jsfiddle.net/bdB65/)

Lyly answered 14/5, 2014 at 15:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.