Reputation: 12890
I have a DIV
element that I want to clip.
I'm able to use -webkit-clip-path
to reference an SVG clipPath
element and clip the element:
Example HTML
<svg width="0" height="0">
<clipPath id="clipping">
<polygon points="0 100, 300 30, 220 290" />
</clipPath>
</svg>
<div id="tiles"></div>
Example CSS
#tiles {
background:red;
width:300px;
height:300px;
-webkit-clip-path: url(#clipping);
}
See the JSFiddle.
But how can I cut a shape out of that shape? For example, put another triangle in the red triangle? How can I mask the clipping path?
I've seen some resources from a few years ago saying that Firefox supports it, but I need it to work for Chrome, so I haven't even tried getting it to work with Firefox.
I've read that Chrome supports -webkit-mask-image
, and I've seen examples of it working (see the Twitter bird example). But when I tried to recreate it on jsfiddle, I realized that it works on external SVG files but not inline SVG. See the jsfiddle.
Clipping a clipping path doesn't work, and masking a clipping path doesn't seem to work either, since clipPath
doesn't appear to support the mask
attribute.
Anyone have a solution, or must I wait for Chrome to be capable of this?
Upvotes: 4
Views: 7656
Reputation: 64264
When you set the clippath polygon, you are not limited to convex shapes.
If you specify
<polygon points="0 100, 220 290, 300 30, 220 100, 220 220, 180 100, 220 100, 300 30"></polygon>
That will draw an external triangle (the same that you had) and then go inside it and cut another triangle.
If you do it like this, you just have to remember to draw the inner triangle in the oposite turning sense than the outter triangle
EDITING
Yes, you can clip a clip.
See this updated demo
The CSS is
<svg width="0" height="0">
<clipPath id="clip1">
<polygon points="0 100, 220 290, 300 30"></polygon>
</clipPath>
<clipPath id="clip2" clip-path="url(#clip1)">
<polygon points="0 0, 9999 0, 9999 9999, 0 9999, 0 0, 150 140, 180 190, 220 30, 150 140"></polygon>
</clipPath>
</svg>
2 things to note:
first, the syntax for this is not very userfriendly. As far as I know, if you want to use say 5 polygons, you have to chain all of them one to the other.
second, since you want (or at least seems that you want) to have the polygons "cut thru", you have to make them 'negative' . That's achieved wrapping it with a huge rectangle around it ( The 9999 coordinates). The good news about that is that it is a code that you can copy paste.
Anyway, as you have been warned in another answer, this technology isn't really really stable.
Upvotes: 3
Reputation:
Clipping is currently immature in the browsers so you will most likely face problems using clip-path
and/or SVG.
If I may suggest another approach then you could use the Canvas element as an engine to draw triangles, clip them and so forth. This will work in most of the current browsers, even IE.
For example using the following code will result in this:
The element can now be used as any other element and has transparency if you need to use it as an overlay.
The process is simple - a generic function to take the polygon points as an array and a color:
function drawPolygon(points, color) {
ctx.beginPath();
ctx.moveTo(points[0], points[1]);
for(var i = 2; i < polygon.length; i+=2)
ctx.lineTo(points[i], points[i+1]);
ctx.closePath();
ctx.fillStyle = color;
ctx.fill();
}
Now all we need to do is to call once for the outer triangle, change composite mode so we'll "punch hole" with the next draw:
/// draw first red triangle
drawPolygon(polygon, '#f00');
/// composite mode to clear the first drawing with the next
ctx.globalCompositeOperation = 'destination-out';
/// a smaller triangle will make the hole (color not important here)
drawPolygon(polygon2, '#00f');
ONLINE DEMO
You can even set the canvas as a background image to another element:
divId.style.backgroundImage = canvas.toDataURL();
I'm using easyCanvasJS in the demo but it is not required for this to work (it's used here to setup canvas etc.).
Upvotes: 2