12

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>

在此处输入图像描述

4

1 回答 1

4

更多的是扩展评论而不是答案:

这似乎是一种奇怪的行为,我玩了一些Paths,并尝试使用Geometry.GetWidenedPathGeometry对数据本身应用稍微不同的缩放效果,但并没有走得太远。

问题的根本原因似乎是 WPF 中选择命中检测容差的方式,Brendan Clark 在 MSDN 上对类似问题有两个答案,似乎从未修复过。

本质上,所使用的命中测试容差似乎是从几何本身的基本尺寸得出的绝对值,而不是渲染/转换后的尺寸。因此,虽然这对于您制作较小的大形状或实际上保持较小的小形状很好,但当按比例放大小形状时(如您所见),它会开始变得非常不准确。

即相对于小形状大小的小命中测试容差很好,但是当形状和容差都按比例放大时,这开始看起来很糟糕。

在一个线程中提出的解决方案是将形状缩放到您需要的最大尺寸,并在您希望它们更小时将它们缩小(这不是您的解决方案)。嗯。

看起来你可能会遇到一些转变。我会尝试看看我是否能想出更好的方法。

我正在查看的链接:

http://social.msdn.microsoft.com/Forums/vstudio/en-US/8708e340-f734-4cf4-b91d-28b49fee2b72/hittest-is-buggy-not-accurate-for-transformed-scaled-etc-visuals?论坛=wpf

http://social.msdn.microsoft.com/Forums/vstudio/en-US/b307676b-d8b2-4af0-9f6f-1e150eed97ba/hittesting-with-a-scaled-path-doesnt-work?forum=wpf

于 2013-10-12T15:03:59.253 回答