2

Hi,

I have this shape I made in SVG:

<svg xmlns="http://www.w3.org/2000/svg" height="280" width="130">
 <defs>
  <clipPath id="buscar" clipPathUnits="objectBoundingBox">
   <polygon points="0.08,0 0.08,0.07 0.14,0.12 0.14,0.96 0.92,0.964 0.97,0.923 0.97,0.15 0.99,0.13 0.99,0"/>
  </clipPath>
 </defs> 
 <polygon points="10.2539,0.918692 10.2539,1.24946 9.92309,19.111 17.8616,31.6803 18.1923,269.669 119.077,270.165 125.858,259.746 125.692,42.9264 128.338,37.3033 128.338,0.918692 10.2539,0.918692" id="p2" style="fill:none; stroke-width: 1px;" stroke="#555555"/>
</svg>

both shapes are exactly the same but the coords in clip-path are in objectBoundingBox units and I want to use that as well for the polygon below so I can have the exact same coords for both. Is it possible?

My goal is to have a clipped div that is surrounded by a border with the same shape of course.

Thank you.

Cain Nuke
  • 2,843
  • 5
  • 42
  • 65
  • objectBoundingBox units are for clipPaths, masks and filters. If you are creating one of those then your shape's co-ordinates could be interpreted as being in such units if you wanted. If not then what do you mean by objectBoundingBox units, what object's bounding box? – Robert Longson Jun 12 '16 at 07:33
  • You mean I cant use objectBoundingBox units in this example? – Cain Nuke Jun 12 '16 at 07:34
  • Your question is basically the equivalent of "can I use light fittings in my unicorn?" I've no idea how to interpret such a question. What object's bounding box are you talking about for the units? – Robert Longson Jun 12 '16 at 07:38
  • I am using the SVG image as a background like this: background:url("images/shape.svg") no-repeat 0 0 / 100% 100%; – Cain Nuke Jun 12 '16 at 07:39
  • Lovely, describe what effect you want to achive and how that differs from the effect you're currently getting with the above markup. – Robert Longson Jun 12 '16 at 07:44
  • Its the same effect. The thing is that I am using the same image as a clip-path as well like this: clip-path:url("images/shape.svg#clip"); and there I am using objectBoundingBox units so I want to use the same values for both instead of having to draw the same shape twice for each set of units. Is it clear now? – Cain Nuke Jun 12 '16 at 07:47
  • It looks like this: http://i.stack.imgur.com/15wEG.png – Cain Nuke Jun 12 '16 at 07:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/114450/discussion-between-robert-longson-and-cain-nuke). – Robert Longson Jun 12 '16 at 07:59
  • After reading your comment threads with @Robert and Paul more thoroughly and looking at the Q edit you made, I think you should consider re-asking this as a new question. As is, I think this question is falling in [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) territory. There is a lot of "noise" in the question about objectBoundingBox units that pertain to your attempted solution to a problem without a full explanation of the problem you have. Your edit stating your goal should be expanded as the bulk of a new question, not just the one-liner as is. – Steve Ladavich Jun 21 '16 at 20:01
  • I tried that but my question was flagged as a duplicate despite it was totally different. – Cain Nuke Jun 22 '16 at 14:31
  • I see your second question that was flagged as a duplicate. It's still heavy on the "objectBoundingBox units" stuff. You should try drafting a question about your end goal. I think it would be something along the lines of: "I have an SVG alpha map for a shape. How can I use it to clip the path of a div in a way that's (1) reusable/resizeable and (2) such that the div has a border." I think I see where you were coming from when asking about the bounding box units, but your understanding was a little off (for the reasons Robert & Paul explained). That misunderstanding confuses your issue. – Steve Ladavich Jun 22 '16 at 15:53
  • Check out this article on [SVG clipping](https://sarasoueidan.com/blog/css-svg-clipping/) and others by the same author. I think the examples could help illustrate how clipPath and objectBoundingBox work. – Steve Ladavich Jun 22 '16 at 16:01

2 Answers2

0

As Robert has tried to tell you, your question cannot be answered because it makes no sense.

objectBoundingBox units are only used for things that are applied to other elements. Examples would be: gradients, masks etc. For example, you can define a gradient to be relative to the element it is being applied to, so that it "fits" whatever the other element's size is.

You can't define a standalone polygon in objectBoundingBox units, because there is no other element to base the units on.


You haven't been very clear in what you want, but perhaps you mean that given an image and a polygon you want to convert the the polygon so that it is defined in objectBoundingBox units relative to that image?

If that is what you mean, then the answer is that there is no easy way to do it. A couple of approaches you could take would be:

  1. Given image width W and height H, go through the polygon manually and divide all the X coordinates by W and a;ll the Y coordinates by H.

    So if the image was 300x400, then the first coordinates of your polygon would become:

    (121.67/300), (271.958/400) or 0.41,0.68

  2. Another way would be to use an SVG editor and scale the image and polygon down together so that they are in the top left of the document from 0,0 to 100,100. Then, when you save the new SVG, all your polygon coordinates will be in the range 0-100. You can then go through and divide all the values by 100 to get your objectBoundingBox coord values. It's a bit tedious, but it could save you a lot of time if you have a lot of coordinates to convert.


On the other hand, if you want to use the same polygon for both the image and the clipping path, then you would need to have a viewBox of "0 0 1 1". For example:

<svg width="400px" height="400px" viewBox="0 0 1 1">
  <defs>
    <clipPath id="myclip" clipPathUnits="objectBoundingBox">
      <use xlink:href="#poly"/>
    </clipPath>
  </defs>

  <polygon id="poly" points="0.1 0.1 0.9 0.5 0.1 0.9"
           fill="none" stroke="red" stroke-width="0.02"/>

  <image xlink:href="http://placekitten.com/200/200" width="1" height="1"
         clip-path="url(#myclip)"/>
</svg>

Be aware that there are some limitations to this approach. You may have some issues with both things aligning if they don't have the same aspect ratio as each other.

Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • Then why can you use objectBoundingBox in clip-path? What I want to do is very simple. I want to use the SVG image as a background for divs containers on my page which vary in size. The thing is that I also will be using the same SVG image as clip-path and in order to make it fit the container I have to use objectBoundingBox units for those. But I dont see the point in drawing the same shape twice for each unit system. Thats why I want to use objectBoundingBox units in both. I think I cant be any clearer than that. – Cain Nuke Jun 13 '16 at 09:07
  • Because clipPath is like gradients and masks - it is applied to other objects. You could do what Robert has already suggested and use a viewBox of `"0 0 1 1"`. You can then define all your coordinates in the range 0->1, and the same polygon could be used to render as an image *and* as a clipPath. However, if you need the image and the clipPath to line up, you may have trouble unless the SVG is square or you are willing to let the image stretch (by setting `preserveAspectRatio="none"). – Paul LeBeau Jun 13 '16 at 09:28
  • You mean I have to divide the current coordinates by the width and height and then declare a viewBox of 0 0 1 1? – Cain Nuke Jun 13 '16 at 09:44
  • I've taken another guess at what you want and added more to my answer. – Paul LeBeau Jun 13 '16 at 09:59
  • Yes, its kinda like that. But why is the image inside the SVG tags? What about loading the SVG externally as the background for a div container? Like: div {clip-path:url("images/shape.svg#poly");background:url("images/shape.svg") no-repeat 0 0 / 100% 100%;width:400px;height:400px;} – Cain Nuke Jun 13 '16 at 12:22
  • And your guess was right. What I am pretty much trying to do is adding a border like that to the clipped container of the same shape. This is the only way I can think of to do that. – Cain Nuke Jun 13 '16 at 12:38
  • You could clip a `
    ` but like I said, you will have to be careful if you want the clipped element and the polygon to stay lined up. Also, browser support for clipping HTML elements varies. http://caniuse.com/#feat=css-clip-path
    – Paul LeBeau Jun 13 '16 at 13:30
  • I will give it a try anyway. I will let you know. – Cain Nuke Jun 13 '16 at 14:59
  • I tried but it didnt work. I edited my question to make it even clearer. – Cain Nuke Jun 14 '16 at 14:29
  • Please don't completely rewrite your question. It means all the comments and answers no longer make sense. – Paul LeBeau Jun 14 '16 at 15:17
  • I didnt change the question. Its the same thing but with more details – Cain Nuke Jun 14 '16 at 15:53
  • I think the limitations mentioned (ie. regarding aspect ratio) are a subset of limitations resulting from trying to create a border with a scaled shape rather than a dilated one. I think my answer addresses those limitations without introducing any new ones. I'm very curious to see if you see any issue with using a filter to dilate the shape. – Steve Ladavich Jun 20 '16 at 19:52
0

Try using the SVG feMorphology filter to achieve what you want... https://stackoverflow.com/a/37930426/5776618

The approach of shrinking/enlarging the shape in your example will not work because the irregular shape in your example will cause corners to be cut -- you'll end up with a non-uniform border.

To restate what I said in the linked answer above...

The key aspects of using the dilation filter are:

  • Create matching and shapes of height and width
  • Clip both with the desired shape path/polygon
  • Use filter to dilate the clipped rect to make a border

.clipper{
  clip-path: url(#clip_shape);
}
.dilate{
  filter: url("#dilate_shape");
}
<svg xmlns="http://www.w3.org/2000/svg" height="300" width="300">
 <defs>
  <clipPath id="clip_shape" clipPathUnits="objectBoundingBox">
    <polygon points="0.08,0 0.08,0.07 0.14,0.12 0.14,0.96 0.92,0.964 0.97,0.923 0.97,0.15 0.99,0.13 0.99,0"/>
  </clipPath>
   <filter id="dilate_shape">
      <feMorphology operator="dilate" in="SourceGraphic" radius="3" />
   </filter>
   
 </defs> 
 
 <g transform="translate(5,5)">
   <g class="dilate">
     <rect class="clipper" x=0 y=0 height="200px" width="200px" fill="lightgreen"></rect>
   </g>
   <image class="clipper" xlink:href="http://placekitten.com/200/200" height="200px" width="200px">
 </g>
</svg>
Community
  • 1
  • 1
Steve Ladavich
  • 3,472
  • 20
  • 27
  • Thats nice but how will that work with a svg used as background? – Cain Nuke Jun 21 '16 at 15:31
  • It will work the same as the `` element you have in your example code. Elements/shapes in SVG are painted in the order they are written so if you want this to be in the background, place it first. Everything after will be drawn on top. If I'm misunderstanding your question, feel free to clarify. Try it out -- that should be a good, real life test to see if it behaves like you want it to. – Steve Ladavich Jun 21 '16 at 16:47
  • Sorry but I fail to see how can I use your example for a background. Do I have to remove the image tag? – Cain Nuke Jun 22 '16 at 14:30
  • I'm not sure what you mean by "for a background". As far as removing the image tag, this example is meant to be illustrative it shows how to both clip a shape from an element and add a border. You may have to tweak some things for your case, ie. if you don't want to clip an image, swap out the image tag with something you want to clip. – Steve Ladavich Jun 22 '16 at 15:37
  • I mean like this: div {clip-path:url("images/shape.svg#poly");background:url("images/shape.svg") no-repeat 0 0 / 100% 100%;width:400px;height:400px;} – Cain Nuke Jun 23 '16 at 02:16
  • As said in comments to your question, I think you should consider asking a new question geared specifically toward what problem you're trying to solve. I think that I (and others) are having to guess at things to help you solve your problem when it should be communicated clearly. Case and point, you want to make an img as a background in this approach, but your question makes no mention of this. Answerers can only answer the question asked -- you progressively having to clarify by adding more detail is a sure sign your original question wasn't specific enough. – Steve Ladavich Jun 23 '16 at 18:03