2012-07-10 14 views

risposta

4

Per questo motivo è necessario implementare animazioni a scorrimento.

Guidelines for touch in WPF apps

Non ho provato io stesso, ma qui è quello che sembra essere un open source repo for a WPF carousel che potrebbe valere la pena dare un'occhiata a

Blog entry about swipe animation in WPF

Cambiare la immagine sul desiderato "movimento a scorrimento" :)

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

Spero che aiuti!

Ecco (a proposito) il controllo a rotazione sul secondo link nel caso in cui scompare come il precedente:

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

+0

Questo sembra promettente, darà uno scatto dopo questa sera. Grazie @Daniela –

+0

Il tuo secondo link è rotto, potresti fornire un'alternativa? – Shaharyar

+0

Quel post sembra sparito, ma ho trovato un progetto opensource - Aggiungerò quel link –