2013-10-11 2 views
11

Вводное тестирование результатов дает неверные результаты по элементу Path с большими масштабными коэффициентами в свой RenderTransform.Неправильное тестирование на преобразование Path

Следующий 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 курсор появляется, хотя его положение способ вне формы.

enter image description here

С большим Пути и меньшего масштаба факторы Проблема исчезает, и курсор ведет себя, как ожидалось.

<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> 

enter image description here

Выполнение явного хита теста, как этот

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), мне также необходимо преобразовать кисти заливки (что связано не только с установкой их преобразования, но и с их окном просмотра).

Кроме того, фактическое преобразование - это не только масштабирование, но и матричная трансформация, которая также вращается и преобразуется.


Следует также отметить, что проблема также возникает с другими геометриями и дополнительными преобразованиями. Например, преобразованный Путь с RectangleGeometry показывает аналогично неправильное поведение.

Неверные с крупномасштабными факторами:

<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> 

enter image description here

Правильные с мелких факторов:

<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> 

enter image description here

+0

Решение: * не использовать масштабные коэффициенты *. Нет, просто шучу. Это происходит, если вы изменили «RenderTranform» на «LayoutTransform»? –

+0

Уже пытался, что хотя LayoutTransform не будет вариантом. Во всяком случае, он ведет себя одинаково с LayoutTransform. – Clemens

+0

Вы рассматривали использование 'RectangleGeometry.Transform' вместо' Path. [Render | Layout] Transform'? Поскольку у вас есть доступ к самой геометрии, вы можете заставить свою фигуру визуализировать уже преобразованную геометрию, а затем ударное тестирование должно быть более естественным. – heltonbiker

ответ

3

Больше расширенного комментария, чем ответ:

Это похоже на странное поведение, у меня была игра с некоторыми Paths, и я попытался использовать Geometry.GetWidenedPathGeometry, чтобы применить немного другой эффект масштабирования для самих данных, но не очень далеко.

Основная причина проблемы, по-видимому, заключается в том, что в WPF выбран толерантность обнаружения попадания, есть два ответа на подобные вопросы в MSDN от Брендана Кларка, похоже, что это никогда не было исправлено.

По существу, применяемый допуск по тестированию ударов является абсолютным значением, полученным из базового размера самой геометрии, а не для визуализированного/преобразованного размера. Таким образом, хотя это прекрасно для больших фигур, которые вы делаете меньшими или даже маленькими фигурами, которые вы держите в малом размере, это начнет становиться довольно неточным, когда небольшие фигуры масштабируются (как вы уже нашли).

I.e. Небольшой критерий тестирования ударов относительно размера маленькой фигуры в порядке, но когда форма и толерантность становятся все более масштабными, это начинает выглядеть ужасно.

Предлагаемое решение в одном потоке предназначалось для масштабирования фигур до максимального размера, необходимого вам, и масштабирования их вниз, когда вы хотите, чтобы они были меньше (что не является для вас решением). Еа.

Похоже, вы можете столкнуться с некоторыми трансформациями. Я постараюсь посмотреть, смогу ли я придумать что-нибудь получше.

Ссылки Я смотрел на:

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

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

+0

Спасибо за предоставление этого объяснения и ссылок. Это то, что я искал. – Clemens

+1

Рад, что это было полезно = D – Chris

Смежные вопросы