WPF图像滑动以更改iOS中的图像

时间:2012-07-10 11:05:25

标签: c# wpf touchscreen

有人能指出一些代码示例,说明如何实现类似于iOS中的库,您可以在Windows 7上使用触摸屏显示器时左右滑动以更改图像吗?

1 个答案:

答案 0 :(得分:4)

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

Guidelines for touch in WPF apps

我自己没试过,但这里似乎是一个开源的回购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>