变焦/夹持检测在WPF用户控件(Zoom/Pinch detection in a WPF User

2019-10-20 23:08发布

我想知道我怎么可以检测到用户控件做了一个放大/缩放手势? 以下是我的XAML代码。 我怎样才能在“Grid_OnManipulationDelta”或“Grid_OnManipulationCompleted”的方法检测呢? 为感谢名单提前帮助。

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

Answer 1:

总之,是的。 最快捷的方式起床,用捏/缩放手势运行的方法是在“TranslateZoomRotateBehavior”附加到你要控制在用户控件或元素。 这将允许您使用单一和多点触摸事件来控制元素的平移,缩放和旋转。

如果你想手动做到这一点,那么我建议你看看此行为的定制版本我已经张贴在Codeplex上 。

特别是, 在这个类ManipulationDeltaHandler 。



Answer 2:

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


文章来源: Zoom/Pinch detection in a WPF UserControl