RenderTransform
输入命中测试在其属性中具有大比例因子的路径元素上产生不正确的结果。
以下 XAML 定义了一个带有实心圆圈和Hand
光标的路径。
<Canvas Background="LightGray">
<Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
<Path.Data>
<EllipseGeometry RadiusX=".5" RadiusY=".5" Center="1,1"/>
</Path.Data>
<Path.RenderTransform>
<ScaleTransform ScaleX="150" ScaleY="150"/>
</Path.RenderTransform>
</Path>
</Canvas>
如下图所示,Hand
光标出现了,尽管它的位置在形状之外。
使用更大的路径和更小的比例因子,问题消失并且光标按预期运行。
<Canvas Background="LightGray">
<Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
<Path.Data>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="100,100"/>
</Path.Data>
<Path.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</Path.RenderTransform>
</Path>
</Canvas>
像这样执行显式命中测试
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var canvas = (UIElement)sender;
var hitElement = canvas.InputHitTest(e.GetPosition(canvas));
Trace.TraceInformation("hitElement = {0}", hitElement);
}
在画布上的鼠标事件处理程序中会给出相同的错误结果。在缩放的路径之外清楚地单击鼠标仍将路径返回为命中元素。
还值得注意的是,该问题并未出现在 Silverlight 中。
现在的问题是:这种行为的原因是什么,如何避免?请注意,我不能简单地更改 Path 元素的原始大小,因此“不要使用大比例因子”之类的答案不会有帮助。
我当前的解决方法不是通过 RenderTransform 转换路径,而是转换数据(通过将转换应用于Geometry.Transform
属性)。但由于可能有复杂的填充(例如使用 ImageBrush),我也必须变换填充画笔(这不仅涉及设置它们的变换,还涉及它们的视口)。
此外,实际的变换不仅是缩放,而且是一个 MatrixTransform,它也可以旋转和平移。
还可能值得注意的是,其他几何形状和其他变换也会出现问题。例如,带有 RectangleGeometry 的转换后的 Path 显示出类似的错误行为。
大比例因子不正确:
<Canvas Background="LightGray">
<Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
<Path.Data>
<RectangleGeometry Rect=".5,.5,1,1"/>
</Path.Data>
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="150" ScaleY="150"/>
<RotateTransform Angle="45" CenterX="150" CenterY="150"/>
<TranslateTransform X="100"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Canvas>
用小比例因子校正:
<Canvas Background="LightGray">
<Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
<Path.Data>
<RectangleGeometry Rect="50,50,100,100"/>
</Path.Data>
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
<RotateTransform Angle="45" CenterX="150" CenterY="150"/>
<TranslateTransform X="100"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Canvas>