【问题标题】:WPF image swipe to change image like in iOSWPF 图像滑动以更改图像,就像在 iOS 中一样
【发布时间】:2012-07-10 11:05:24
【问题描述】:

谁能告诉我一些代码示例,了解如何实现一个画廊,如 iOS 中的画廊,您可以在 Windows 7 上使用触摸屏显示器时左右滑动来更改图像?

【问题讨论】:

    标签: c# wpf touchscreen


    【解决方案1】:

    您需要为此实现类似滑动的动画。

    Guidelines for touch in WPF apps

    我自己没有尝试过,但这里似乎是一个开源 repo for a WPF carousel,可能值得一看

    Blog entry about swipe animation in WPF

    在所需的“滑动移动”上更改图像:)

    Free animation libraries if you don't want to create the animation yourself

    希望对你有帮助!

    这是(顺便说一下)第二个链接中的轮播控件,以防它像上一个一样丢失:

    Michael Palotas的代码

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Threading;
    
    namespace WPFDemo
    {
        public class CarouselControl : Canvas
        {
            public CarouselControl()
            {
                _timer.Tick += new EventHandler(TimerTick);
                _timer.Interval = TimeSpan.FromMilliseconds(10);
            }
    
            public DateTime _previousTime;
            public DateTime _currentTime;
    
            public void ReInitialize()
            {
                Init();
            }
    
            protected override void OnInitialized(EventArgs e)
            {
                base.OnInitialized(e);
                Init();
            }
    
            public delegate void OnElementSelectedHandler(object sender);
            public event OnElementSelectedHandler OnElementSelected;
    
            public void SelectElement(FrameworkElement element)
            {
                if (element != null)
                {
                    _previousTime = DateTime.Now;
    
                    RotateToElement(element);
    
                    if (OnElementSelected != null)
                        OnElementSelected(element);
                }
            }
    
            private const double DEFAULT_ROTATION_SPEED = 200;
            private const double MINIMUM_ROTATION_SPEED = 1;
            private const double MAXIMUM_ROTATION_SPEED = 1000;
            private double _rotationSpeed = DEFAULT_ROTATION_SPEED;
            public double RotationSpeed
            {
                get
                {
                    return _rotationSpeed;
    
                }
                set
                {
                    _rotationSpeed = Math.Min(Math.Max(value, MINIMUM_ROTATION_SPEED), MAXIMUM_ROTATION_SPEED);
                }
            }
    
            private const double DEFAULT_LOOKDOWN_OFFSET = 0;
            private const double MINIMUM_LOOKDOWN_OFFSET = -100;
            private const double MAXIMUM_LOOKDOWN_OFFSET = 100;
            private double _lookdownOffset = DEFAULT_LOOKDOWN_OFFSET;
            public double LookDownOffset
            {
                get
                {
                    return _lookdownOffset;
    
                }
                set
                {
                    _lookdownOffset = Math.Min(Math.Max(value, MINIMUM_LOOKDOWN_OFFSET), MAXIMUM_LOOKDOWN_OFFSET);
                }
            }
    
            private const double DEFAULT_FADE = 0.5;
            private const double MINIMUM_FADE = 0;
            private const double MAXIMUM_FADE = 1;
            private double _fade = DEFAULT_FADE;
            public double Fade
            {
                get
                {
                    return _fade;
    
                }
                set
                {
                    _fade = Math.Min(Math.Max(value, MINIMUM_FADE), MAXIMUM_FADE);
                }
            }
    
            private const double DEFAULT_SCALE = 0.5;
            private const double MINIMUM_SCALE = 0;
            private const double MAXIMUM_SCALE = 1;
            private double _scale = DEFAULT_SCALE;
            public double Scale
            {
                get
                {
                    return _scale;
    
                }
                set
                {
                    _scale = Math.Min(Math.Max(value, MINIMUM_SCALE), MAXIMUM_SCALE);
                }
            }
    
            private void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                SelectElement(sender as FrameworkElement);
            }
    
            private void RotateToElement(FrameworkElement element)
            {
                if (element != _currentlySelected)
                {
                    _currentlySelected = element;
                    int targetIndex = Children.IndexOf(element);
    
                    double degreesToRotate = GetDegreesNeededToPlaceElementInFront(_currentRotation, targetIndex, TotalNumberOfElements);
                    _targetRotation = ClampDegrees(_currentRotation - degreesToRotate);
    
                    StartRotation(degreesToRotate);
                }
            }
    
            internal static double GetDegreesNeededToPlaceElementInFront(double currentRotation, int targetIndex, int totalNumberOfElements)
            {
                double rawDegrees = -(180.0 - (currentRotation + 360.0 * ((double)targetIndex / (double)totalNumberOfElements)));
    
                if (rawDegrees > 180)
                    return -(360 - rawDegrees);
    
                return rawDegrees;
            }
    
            private double RotationAmount
            {
                get
                {
                    return (_currentTime - _previousTime).TotalSeconds * _rotationSpeed;
                }
            }
    
    
            private const double INTERNAL_SCALE_COEFFICIENT = 0.6;
            private void Init()
            {
                _previousTime = _currentTime = DateTime.Now;
    
                X_SCALE = CenterX * INTERNAL_SCALE_COEFFICIENT;
                Y_SCALE = CenterY * INTERNAL_SCALE_COEFFICIENT;
    
                foreach (FrameworkElement element in Children)
                {
                    element.MouseLeftButtonDown += new MouseButtonEventHandler(element_MouseLeftButtonDown);
                    element.Cursor = Cursors.Hand;
                }
    
                SelectElement(GetChild(0));
    
                SetElementPositions();
            }
    
    
            private FrameworkElement _currentlySelected = null;
            public FrameworkElement CurrentlySelected { get { return _currentlySelected; } }
            protected double CenterX { get { return this.Width / 2.0; } }
            protected double CenterY { get { return this.Height / 2.0; } }
    
            protected double X_SCALE = 0;
            protected double Y_SCALE = 0;
    
            protected DispatcherTimer _timer = new DispatcherTimer();
            private double _rotationToGo = 0;
    
            private int TotalNumberOfElements { get { return Children.Count; } }
            protected double _currentRotation = 0;
    
            protected double _targetRotation = 0;
    
    
            protected virtual void TimerTick(object sender, EventArgs e)
            {
                _currentTime = DateTime.Now;
    
                if ((_rotationToGo < RotationAmount) && (_rotationToGo > -RotationAmount))
                {
                    _rotationToGo = 0;
    
                    if (_currentRotation != _targetRotation)
                    {
                        _currentRotation = _targetRotation;
                    }
                    else
                    {
                        _timer.Stop();
                        return;
                    }
                }
                else if (_rotationToGo < 0)
                {
                    _rotationToGo += RotationAmount;
                    _currentRotation = ClampDegrees(_currentRotation + RotationAmount);
                }
                else
                {
                    _rotationToGo -= RotationAmount;
                    _currentRotation = ClampDegrees(_currentRotation - RotationAmount);
                }
    
                SetElementPositions();
    
                _previousTime = _currentTime;
            }
    
            protected double ClampDegrees(double rawDegrees)
            {
                if (rawDegrees > 360)
                    return rawDegrees - 360;
    
                if (rawDegrees < 0)
                    return rawDegrees + 360;
    
                return rawDegrees;
            }
    
            public void SetElementPositions()
            {
                for (int index = 0; index < TotalNumberOfElements; index++)
                {
                    FrameworkElement element = GetChild(index);
    
                    double elementWidthCenter = GetElementCenter(element.Width, element.ActualWidth);
                    double elementHeightCenter = GetElementCenter(element.Height, element.ActualHeight);
    
                    double degrees = 360 * ((double)index / (double)TotalNumberOfElements) + _currentRotation;
    
                    double x = -X_SCALE * Math.Sin(ConvertToRads(degrees)) - (double.IsNaN(Y_SCALE) ? 0.0 : Y_SCALE / 100.0) * (Math.Cos(ConvertToRads(degrees)) * LookDownOffset);
                    Canvas.SetLeft(element, x + CenterX - elementWidthCenter);
    
                    double y = Y_SCALE * Math.Sin(ConvertToRads(degrees)) - (double.IsNaN(X_SCALE) ? 0.0 : X_SCALE / 100.0) * (Math.Cos(ConvertToRads(degrees)) * LookDownOffset);
                    Canvas.SetTop(element, y + CenterY - elementHeightCenter);
    
                    ScaleTransform scale = element.RenderTransform as ScaleTransform;
                    if (scale == null)
                    {
                        scale = new ScaleTransform();
                        element.RenderTransform = scale;
                    }
    
                    scale.CenterX = elementWidthCenter;
                    scale.CenterY = elementHeightCenter;
                    scale.ScaleX = scale.ScaleY = GetScaledSize(degrees);
                    Canvas.SetZIndex(element, GetZValue(degrees));
    
                    SetOpacity(element, degrees);
                }
            }
    
            private FrameworkElement GetChild(int index)
            {
                if (Children.Count == 0)
                    return null;
    
                FrameworkElement element = Children[index] as FrameworkElement;
    
                if (element == null)
                    throw new NotSupportedException("Carousel only supports children that are Framework elements");
    
                return element;
            }
    
            internal static double GetElementCenter(double elementDimension, double elementActualDimension)
            {
                return double.IsNaN(elementDimension) ? elementActualDimension / 2.0 : elementDimension / 2.0;
            }
    
    
            private void SetOpacity(FrameworkElement element, double degrees)
            {
                element.Opacity = (1.0 - Fade) + Fade * GetCoefficient(degrees);
            }
    
            private int GetZValue(double degrees)
            {
                return (int)(360 * GetCoefficient(degrees));
            }
    
            private double GetScaledSize(double degrees)
            {
                return (1.0 - Scale) + Scale * GetCoefficient(degrees);
            }
    
            private double GetCoefficient(double degrees)
            {
                return 1.0 - Math.Cos(ConvertToRads(degrees)) / 2 - 0.5;
            }
    
            private double ConvertToRads(double degrees)
            {
                return degrees * Math.PI / 180.0;
            }
    
            private void StartRotation(double numberOfDegrees)
            {
                _rotationToGo = numberOfDegrees;
                if (!_timer.IsEnabled)
                {
                    _timer.Start();
                }
            }
        }
    }
    

    XAML:

    <UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    x:Class="WPFDemo.SphereControl"
    x:Name="UserControl"
    d:DesignWidth="50" d:DesignHeight="50">
    <UserControl.Resources>
        <Storyboard x:Key="MouseOver">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1.3" KeySpline="0,0,0.5,1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1.3" KeySpline="0,0,0.5,1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Offset)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0.231"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Offset)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.312"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0.729"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="MouseLeave">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="1" KeySpline="0,0,0.5,1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="1" KeySpline="0,0,0.5,1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Offset)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Offset)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="0.312"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </UserControl.Resources>
    <UserControl.Triggers>
        <EventTrigger RoutedEvent="Mouse.MouseEnter">
            <BeginStoryboard Storyboard="{StaticResource MouseOver}" x:Name="MouseOver_BeginStoryboard"/>
        </EventTrigger>
        <EventTrigger RoutedEvent="Mouse.MouseLeave">
            <BeginStoryboard Storyboard="{StaticResource MouseLeave}"  x:Name="MouseLeave_BeginStoryboard"/>
        </EventTrigger>
    </UserControl.Triggers>
    
    <Grid x:Name="LayoutRoot" RenderTransformOrigin="0.5,0.5">
        <Grid.RenderTransform>
            <TransformGroup>
                <ScaleTransform ScaleX="1" ScaleY="1"/>
                <SkewTransform AngleX="0" AngleY="0"/>
                <RotateTransform Angle="0"/>
                <TranslateTransform X="0" Y="0"/>
            </TransformGroup>
        </Grid.RenderTransform>
        <Ellipse Name="Ellipse" >
            <Ellipse.Fill>
                <RadialGradientBrush GradientOrigin="0.258,0.21">
                    <GradientStop x:Name="OuterColor" Offset="0.9"/>
                    <GradientStop x:Name="InnerColor" Offset="0.312"/>
                    <GradientStop Color="#FFFFFFFF" Offset="0"/>
                </RadialGradientBrush>
            </Ellipse.Fill>
        </Ellipse>
    </Grid>
    

    【讨论】:

    • 这看起来很有希望,今晚晚些时候会试一试。谢谢@Daniela
    • 你的第二个链接坏了,你能提供一个替代方案吗?
    • 那篇文章好像不见了,但我找到了一个开源项目——我会添加那个链接
    猜你喜欢
    • 2016-09-08
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    相关资源
    最近更新 更多