Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

svg - How can I cut one shape inside another?

Is there a way to cut one shape out of another in SVG? For example, I have a rect and an ellipse and I want to make a rect with a transparent hole in the middle. I would imagine it would look something like this:

<set operation="difference" fill="black">
    <rect x="10" y="10" width="50" height="50/>
    <ellipse cx="35" cy="35" rx=10 ry=10/>
</set>

The closest thing I can find is clipping, which will give me the intersection of two shapes. In my example that would result in just the hole being solid and the rest of the rect being transparent.

I looked through Inkscape and there is a difference option in the path menu, but this converts the shapes to paths and then creates a new path. The identity of the shapes is lost so there is no easy way to, for example go into the svg file and change the radius of the ellipse.

Is there any ideas for how I might do this?

question from:https://stackoverflow.com/questions/1983256/how-can-i-cut-one-shape-inside-another

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You must use path element to cut a hole.

See the example from the SVG specification: (you can click this link or the following image to view the real svg file)

svg hole example

<g fill-rule="evenodd" fill="red" stroke="black" stroke-width="3">
    <path d="M 250,75 L 323,301 131,161 369,161 177,301 z"/>

    <path d="M 600,81 A 107,107 0 0,1 600,295 A 107,107 0 0,1 600,81 z
             M 600,139 A 49,49 0 0,1 600,237 A 49,49 0 0,1 600,139 z"/>

    <path d="M 950,81 A 107,107 0 0,1 950,295 A 107,107 0 0,1 950,81 z
             M 950,139 A 49,49 0 0,0 950,237 A 49,49 0 0,0 950,139 z"/>
</g>

For your case:

<path d="M10 10h50v50h-50z M23 35a14 10 0 1 1 0 0.0001 z"
    stroke="blue" stroke-width="2" fill="red" fill-rule="evenodd" />

M10 10h50v50h-50z will draw a rect.

M25 35a10 10 0 1 1 0 0.0001 z will draw a ellipse.

fill-rule="evenodd" will make the hole.


The key point is draw outer shape and inner shapes(holes) in different direction (clockwise vs anti-clockwise).

  • Draw the outer shape clockwise and draw the inner(holes) shapes anti-clockwise.
  • Or conversely, draw the outer shape(holes) anti-clockwise and draw the inner shapes clockwise.
  • Concat the path datas of outer shape and inner shapes(holes).

You can cut more holes by concat more hole path data.

This image explain how to cut a hole:

This image explain how to cut a hole

See w3c docs: SVG Arc Commands and SVG fill-rule Property.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...