如何旋转PathGeometry实现心形图片裁剪并支持缩放?
问题描述
最终目标
使用心形形状裁剪图片。
尝试过程
已将SVG路径数据转换为等效的Geometry对象,但需要旋转最终的Geometry对象。和WPF不同,PathGeometry和PathFigure类型继承自BindableObject而非VisualElement,没有Rotation属性或RotateTo()、Transform()方法。
当前问题
- 如何解决旋转问题?
- 是否有方法让图片裁剪对象可缩放/调整大小?
当前代码
<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>
截图说明

- 红色:目标心形形状。
- 蓝色:当前裁剪形状,需旋转后得到红色心形。
- 注:蓝色与红色形状为同一路径,仅存在旋转差异。
目标SVG(带旋转)
<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>
未旋转的SVG效果
<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>
参考WPF相关问题:如何垂直翻转PathGeometry?
解决方案
一、解决旋转问题
由于PathGeometry不支持直接旋转,有两种可行方案:
1. 手动计算旋转后坐标(性能优先)
根据目标SVG的旋转参数(225度,旋转中心(150,121)),用旋转公式计算所有路径点的新坐标,直接替换原有路径。
旋转坐标公式(以(cx, cy)为中心旋转θ度):
x' = (x - cx) * cosθ - (y - cy) * sinθ + cx y' = (x - cx) * sinθ + (y - cy) * cosθ + cy
225度对应的cos值≈-0.7071,sin值≈-0.7071,计算后可得到如下旋转完成的心形路径:
<PathGeometry> <PathFigure IsClosed="True" StartPoint="150,21.9"> <PathSegmentCollection> <LineSegment Point="260.7,121" /> <ArcSegment IsLargeArc="True" Point="150,220.1" RotationAngle="90" Size="100,100" SweepDirection="Clockwise" /> <ArcSegment IsLargeArc="True" Point="39.3,121" RotationAngle="90" Size="100,100" SweepDirection="Clockwise" /> <LineSegment Point="150,21.9" /> </PathSegmentCollection> </PathFigure> </PathGeometry>
2. 使用Transform属性(便捷优先)
MAUI中PathGeometry提供了Transform属性,可添加RotateTransform设置旋转角度和中心:
<Image.Clip> <PathGeometry> <PathGeometry.Transform> <RotateTransform Angle="225" CenterX="150" CenterY="121" /> </PathGeometry.Transform> <!-- 保留原有路径代码 --> </PathGeometry> </Image.Clip>
注意需确保旋转中心与路径中心对齐,避免出现偏移。
二、实现裁剪对象的缩放/调整大小
1. 结合ScaleTransform动态缩放
通过TransformGroup同时添加旋转和缩放变换,绑定缩放比例实现动态调整:
<PathGeometry.Transform> <TransformGroup> <RotateTransform Angle="225" CenterX="150" CenterY="121" /> <ScaleTransform ScaleX="{Binding ScaleFactor}" ScaleY="{Binding ScaleFactor}" CenterX="150" CenterY="121" /> </TransformGroup> </PathGeometry.Transform>
在ViewModel中定义ScaleFactor属性,修改该值即可调整裁剪形状大小。
2. 使用Viewbox包裹
将Image放入Viewbox中,通过调整Viewbox的宽高间接缩放裁剪形状,同时保持比例:
<Viewbox WidthRequest="{Binding ClipWidth}" HeightRequest="{Binding ClipHeight}"> <Image Aspect="AspectFill" Source="{Binding .}"> <Image.Clip> <!-- 已旋转的心形PathGeometry --> </Image.Clip> </Image> </Viewbox>
三、替代方案
若上述方法复杂,可直接使用SkiaSharp绘制心形裁剪路径,或转换SVG为Path的Data属性作为裁剪,灵活性更高。
内容的提问来源于stack exchange,提问作者Cfun
相关产品推荐
相关产品推荐

