Clip an image with a shape of heart.
I have converted the svg path data of this source into it's geometry equivalent. Except that I have to rotate the final Geometry
object, unlike in wpf there is no such Rotation
property or RotateTo() ... Transform()
method defined for types PathGeometry
and PathFigure
since both inherit from BindableObject
and not VisualElement
.
<DataTemplate>
...
<Image Aspect="AspectFill"
Source="{Binding .}"
VerticalOptions="Center"
WidthRequest="300">
<Image.Clip>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure IsClosed="False" StartPoint="0,200">
<PathFigure.Segments>
<PathSegmentCollection>
<LineSegment Point="0,0" />
<LineSegment Point="200,0" />
<ArcSegment IsLargeArc="True"
Point="200,200"
RotationAngle="90"
Size="100,100"
SweepDirection="Clockwise" />
<ArcSegment IsLargeArc="True"
Point="0,200"
RotationAngle="90"
Size="100,100"
SweepDirection="Clockwise" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Image.Clip>
</Image>
...
<DataTemplate>
Red: is the desired shape.
Blue: is the actual clip that needs to be rotated to obtain the red one.
Note that the blue and red shapes are exactly the same shape (data path), with only difference the rotation.
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" height="315" width="342" viewBox="20 -10 315 342">
<defs>
<style type="text/css"><![CDATA[
.outline { stroke:none; stroke-width:0 }
]]></style>
<g id="heart">
<path
stroke="red"
pathLength="1"
stroke-width="5"
d="M0 200 v-200 h200
a100,100 90 0,1 0,200
a100,100 90 0,1 -200,0
z" />
</g>
</defs>
<desc>
a nearly perfect heart
made of two arcs and a right angle
</desc>
<use xlink:href="#heart" class="outline " fill="none" transform="rotate(225,150,121)" />
</svg>
Basically this is what you get without the rotation:
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" height="315" width="342" viewBox="20 -10 315 342">
<defs>
<style type="text/css"><![CDATA[
.outline { stroke:none; stroke-width:0 }
]]></style>
<g id="heart">
<path
stroke="red"
pathLength="1"
stroke-width="5"
d="M0 200 v-200 h200
a100,100 90 0,1 0,200
a100,100 90 0,1 -200,0
z" />
</g>
</defs>
<desc>
a nearly perfect heart
made of two arcs and a right angle
</desc>
<use xlink:href="#heart" class="outline " fill="none"" />
</svg>
ps: I am open to other approaches.
With regards to the svg geometry you can take advantage of many javaScript based tools/libraries to transform paths to "hardcoded" path data commands.
You can use the svg-path-editor to conveniently recalculate all path commands according to rotation.
getBBox()
method to get the appropriate offsets.The final path data should look something like this
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 342 312" style="border:1px solid #ccc; height:90vmin">
<path
d="
M 312.42 170.58
L 171 312
L 29.58 170.58
A 100 100 0 0 1 171 29.16
A 100 100 0 0 1 312.42 170.58
"/></svg>
BTW: if arc rx
and ry
radii parameters (1. and 2. A
command parameter) are equal – the arc is perfectly circular (or non-elliptical) so a specified rotation angle doesn't have any rendering effect – so it can be set to 0.
According to MS docs: "How to: Create an Elliptical Arc" you should be able to translate these SVG values like so
wpf/xaml | svg |
---|---|
StartPoint="312.42, 170.58" |
M 312.42 170.58 |
LineSegment Point="171,312" |
L 171 312 |
LineSegment Point="29.58,170.58" |
L 29.58 170.58 |
ArcSegment Size="100,100" RotationAngle="0" IsLargeArc="True" SweepDirection="Clockwise" Point="171,29.16" |
A 100 100 0 1 1 171 29.16 |
wpf/xaml arc to SVG terminology: Size=[rx,rx] (x and y radius ... calling it "size" ... no comment), RotationAngle=x-axis-rotation, IsLargeArc=largeArc flag, SweepDirection=sweep flag(1 =clockwise; 0=counterclockwise) Point=[x,y] (final on-path point) See also "W3C spec: §9.3.8. The elliptical arc curve commands" |
|
ArcSegment Size="100,100" RotationAngle="0" IsLargeArc="True" SweepDirection="Clockwise" Point="312.42,170.58" |
A 100 100 0 1 1 312.42 170.58 |