WPF UserControl 中的缩放/捏合检测 [英] Zoom/Pinch detection in a WPF UserControl

查看:28
本文介绍了WPF UserControl 中的缩放/捏合检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何检测 UserControl 上的缩放/捏合手势?以下是我的 XAML 代码.我如何在Grid_OnManipulationDelta"或Grid_OnManipulationCompleted"方法中检测到这一点?提前感谢您的帮助.

I want to know how can I detect a Zoom/pinch gesture made on UserControl? Following is my XAML code. How can i detect this in "Grid_OnManipulationDelta" or "Grid_OnManipulationCompleted" methods? Thanx for the help in advance.

<UserControl x:Class="HCMainWPF.Views.MainView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:views="clr-namespace:HCMainWPF.Views" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Name="ZMainView">
    <Canvas x:Name="grid">
        <Canvas.RenderTransform>
            <ScaleTransform x:Name="zoom" ScaleX="1" ScaleY="1" />
        </Canvas.RenderTransform>
        <Canvas.Triggers>
            <EventTrigger RoutedEvent="Grid.ManipulationCompleted">
                <EventTrigger.Actions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Duration="00:00:02" From="320" Storyboard.TargetName="ZMainView"
                        Storyboard.TargetProperty="Height"  To="960"/>
                            <DoubleAnimation Duration="00:00:02" From="270" Storyboard.TargetName="ZMainView"
                        Storyboard.TargetProperty="Width" To="810"/>
                            <DoubleAnimation Duration="00:00:02" From="1" Storyboard.TargetName="zoom"
                        Storyboard.TargetProperty="ScaleX" To="3"/>
                            <DoubleAnimation Duration="00:00:02" From="1" Storyboard.TargetName="zoom"
                        Storyboard.TargetProperty="ScaleY" To="3"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger.Actions>
            </EventTrigger>
        </Canvas.Triggers>
        <Grid Height="280" Width="280" IsManipulationEnabled="True"
            ManipulationStarting="Grid_OnManipulationStarting"
            ManipulationDelta="Grid_OnManipulationDelta" 
            ManipulationCompleted="Grid_OnManipulationCompleted">
            <Grid.RowDefinitions>
                <RowDefinition Height="1.66*"/>
                <RowDefinition Height="1.66*"/>
                <RowDefinition Height="1.66*"/>
                <RowDefinition Height="1.66*"/>
                <RowDefinition Height="1.66*"/>
                <RowDefinition Height="1.66*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="3.33*"/>
                <ColumnDefinition Width="3.33*"/>
                <ColumnDefinition Width="3.33*"/>
            </Grid.ColumnDefinitions>
        </Grid>
    </Canvas>
</UserControl>

推荐答案

 public class GestureDetector
{
    private readonly uint _pixelPerCm = 38;
    private bool _isGestureDetected = false;

    public bool IsPanningAllowed { get; private set; }
    public bool IsScalingAllowed { get; private set; }
    public bool IsRotatingAllowed { get; private set; }

    public GestureDetector(FrameworkElement uiElement)
    {
        IsPanningAllowed = false;
        IsScalingAllowed = false;
        IsRotatingAllowed = false;

        uiElement.ManipulationStarted += (sender, args) =>
        {
            IsPanningAllowed = true;
        };

        double scale = 0.0d;
        double rot = 0.0d;

        uiElement.ManipulationDelta += (sender, args) =>
        {
            const double MIN_SCALE_TRIGGER = 0.05;
            const int MIN_ROTATIONANGLE_TRIGGER_DEGREE = 10;
            const int MIN_FINGER_DISTANCE_FOR_ROTATION_CM = 2;

            var manipulatorBounds = Rect.Empty;
            foreach (var manipulator in args.Manipulators)
            {
                manipulatorBounds.Union(manipulator.GetPosition(sender as IInputElement));
            }

            var distance = (manipulatorBounds.TopLeft - manipulatorBounds.BottomRight).Length;
            var distanceInCm = distance /_pixelPerCm;

            scale += 1-(args.DeltaManipulation.Scale.Length / Math.Sqrt(2));

            rot += args.DeltaManipulation.Rotation;

            if (Math.Abs(scale) > MIN_SCALE_TRIGGER && Math.Abs(rot) < MIN_ROTATIONANGLE_TRIGGER_DEGREE)
            {
                ApplyScaleMode();
            }

            if (Math.Abs(rot) >= MIN_ROTATIONANGLE_TRIGGER_DEGREE && distanceInCm > MIN_FINGER_DISTANCE_FOR_ROTATION_CM)
            {
                ApplyRotationMode();
            }
        };

        uiElement.ManipulationCompleted += (sender, args) =>
        {
            scale = 0.0d;
            rot = 0.0d;
            IsPanningAllowed = false;
            IsScalingAllowed = false;
            IsRotatingAllowed = false;
            _isGestureDetected = false;
        };
    }

    private void ApplyScaleMode()
    {
        if (!_isGestureDetected)
        {
            _isGestureDetected = true;
            IsPanningAllowed = true;
            IsScalingAllowed = true;
            IsRotatingAllowed = false;
        }
    }

    private void ApplyRotationMode()
    {
        if (!_isGestureDetected)
        {
            _isGestureDetected = true;
            IsPanningAllowed = true;
            IsScalingAllowed = true;
            IsRotatingAllowed = true;
        }
    }
}

用法:

 private void uielement_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
        {
            if (_gestureDetector.IsPanningAllowed)
            {
               // Translate
            }
        }

        {
            if (_gestureDetector.IsScalingAllowed)
            {
               // Scale
            }
        }

        {
            if (_gestureDetector.IsRotatingAllowed)
            {
                // Rotate
            }
        }
    }

这篇关于WPF UserControl 中的缩放/捏合检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆