问题
I'm trying to create a responsive SVG Clip Path using a <path>
SVG element. However, I having trouble getting it to work.
I have gotten it to work using more basic shapes such as <circle>
, but not the <path>
element. I have also gotten it to work using static dimensions with the <path>
element.
I used the instructions here as a reference: https://www.smashingmagazine.com/2015/05/creating-responsive-shapes-with-clip-path/. I also looked at similar questions on StackOverflow and other examples, but they mostly deal with basic shapes and not the path variable.
The SVG shape I'm using is a raindrop shape which was exported from Adobe Illustrator.
Here is my code:
HTML
<svg id="raindropSVG" viewBox="0 0 810 1012">
<defs>
<clipPath id="raindropClipPath" clipPathUnits="objectBoundingBox">
<path d="M0,604.4C0,523.7,30.7,408.8,97.5,320,217,160.9,409.2,0,409.2,0S597.2,167.8,717,331c63,85.7,93,196.4,93,274,0,224.5-181.3,407-405,407S0,829.5,0,604.4Z"/>
</clipPath>
</defs>
</svg>
<img src="clipped-image.jpg" alt="" class="clipped-img">
CSS
.clipped-img {
clip-path: url(#raindropClipPath);
width: 100%;
height: auto;
}
#raindropSVG {
width: 0;
height: 0;
}
The idea is that changing the width (or height) of the .clipped-img
should scale the raindrop shape accordingly.
Using clipPathUnits="objectBoundingBox"
is necessary for making the clipPath
responsive. However, as soon as I add this the clipped image disappears.
Where I think I'm going wrong
I suspect that the path specified by the path element is not in relative units, however I don't know how to change the units to relative.
Thanks in advance for all responses!
回答1:
This answer distorts the shape of the clip path so that it always spans the whole image, regardless of its aspect ratio.
With clipPathUnits="objectBoundingBox"
, only coordinates between 0 and 1 will lie inside the bounding rectangle of your image. You have to scale down the path for that.
Fortunately, the viewBox
for your path names its dimensions. Unfortunately, you cannot leave the computation of the scaling to the renderer, but must give a transformation directly: scale(1 / 810, 1 / 1012)
. See the restrictions for the content elements of a <clipPath>
.
Both the SVG 1.1 and the SVG 2 spec name transform
as a possible attribute of the <clipPath>
itself, but neither define the coordinate system it should be applied in. For the sake of browser compatibility, it is probably better to leave that alone and use the transform on the <path>
element, even if I can see that in Firefox there is no difference in the result.
.clipped-img {
clip-path: url(#raindropClipPath);
width: 100%;
height: auto;
}
#raindropSVG {
width: 0;
height: 0;
}
<svg id="raindropSVG">
<defs>
<clipPath id="raindropClipPath" clipPathUnits="objectBoundingBox">
<path transform="scale(0.0012345, 0.00098814)" d="M0,604.4C0,523.7,30.7,408.8,97.5,320,217,160.9,409.2,0,409.2,0S597.2,167.8,717,331c63,85.7,93,196.4,93,274,0,224.5-181.3,407-405,407S0,829.5,0,604.4Z"/>
</clipPath>
</defs>
</svg>
<img src="https://i.stack.imgur.com/zubYX.png" alt="" class="clipped-img">
回答2:
SVG will always be responsive if only viewBox
is specified.
Svg saves image proportions unless the value `preserveAspectRatio ="none" is specified.
Therefore, the path
formativeclip-path
will also be responsive.
A picture added to the SVG using the <image>
tag will also be adaptive and maintain its proportions.
#raindropSVG {
width: 75%;
height: 75%;
}
.clipped-img {
clip-path: url(#raindropClipPath);
}
<svg id="raindropSVG" viewBox="0 0 800 800" preserveAspectRatio="xMinYMin meet">
<defs>
<clipPath id="raindropClipPath" >
<path transform="scale(0.75)" d="M0,604.4C0,523.7,30.7,408.8,97.5,320,217,160.9,409.2,0,409.2,0S597.2,167.8,717,331c63,85.7,93,196.4,93,274,0,224.5-181.3,407-405,407S0,829.5,0,604.4Z"/>
</clipPath>
</defs>
<image class="clipped-img" xlink:href="https://i.stack.imgur.com/zubYX.png" x="0" y="0" width="800" height="800" />
</svg>
来源:https://stackoverflow.com/questions/53618192/create-responsive-svg-clip-path-making-svg-path-responsive