2013-03-10 3 views
14

Ich kann Text mit TranslateTransform scrollen, aber wenn die Animation kurz vor dem Abschluss steht, möchte ich, dass sie erneut beginnt. Wie eine Schlange :)WPF Marquee Textanimation

Das ist, was ich habe:

<StackPanel Orientation="Horizontal" Margin="0,0,0,0"> 
    <StackPanel.RenderTransform> 
     <TranslateTransform x:Name="transferCurreny" X="-40"/> 
    </StackPanel.RenderTransform> 
    <StackPanel.Triggers> 
     <EventTrigger RoutedEvent="StackPanel.Loaded"> 
      <BeginStoryboard> 
       <Storyboard> 
        <DoubleAnimation From="0" To="-900" Duration="00:00:10" 
         Storyboard.TargetProperty="X" 
         Storyboard.TargetName="transferCurreny" 
         RepeatBehavior="Forever"/> 
       </Storyboard> 
      </BeginStoryboard> 
     </EventTrigger> 
    </StackPanel.Triggers> 
    <TextBlock FontSize="25" x:Name="txtKron" Margin="10,0,7,0"/> 
</StackPanel> 

Dies ist, was Ich mag würde:

enter image description here

+0

Was ist die Frage? Was ist das gewünschte Verhalten, welches Verhalten hast du? –

+0

Frage ist; Ich will Text markieren, aber als Schlange – meymetkaplan

+0

Ich verstehe immer noch nicht. Kannst du ein Bild malen? Oder zeigen Sie uns an einen Ort, an dem Sie diesen Effekt schon einmal gesehen haben? –

Antwort

12

So etwas sollte es tun.

Sie können eine Canvas zum StackPanel mit 2 TextBlocks einen Satz hinzufügen 0 und ein Satz zum ActualWidth des StackPanel zu positionieren, dann, wenn der erste Textblock geht Offscreen der andere Block in den Blick kommen.

Der Grund, warum ich Canvas verwendet, weil Canvas das einzige Element ist, das tatsächlich unterstützt ClipToBounds="false" dies die zweite TextBlock sichtbar sein können, auch wenn seine außerhalb der Grenzen des platzierten Canvas selbst

Wir brauchen auch eine IValueConverter zu erhalten der korrekte negative Wert, wenn Sie von rechts nach links blättern möchten.

Ich habe auch Event-Trigger auf SizeChanged hinzugefügt, wenn die Größe des Fensters geändert wird, werden die Animationswerte korrekt aktualisiert.

Code:

namespace WpfApplication9 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 

     public MainWindow() 
     { 
      InitializeComponent(); 
     } 
    } 

    public class NegatingConverter : IValueConverter 
    { 

     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (value is double) 
      { 
       return -((double)value); 
      } 
      return value; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (value is double) 
      { 
       return +(double)value; 
      } 
      return value; 
     } 
    } 
} 

XAML:

<Window x:Class="WpfApplication9.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication9" 
     Title="MainWindow" Height="83" Width="222" Name="UI" Tag="Tol Level"> 
    <StackPanel Orientation="Horizontal" x:Name="stack"> 
     <StackPanel.Resources> 
      <local:NegatingConverter x:Key="NegatingConverter" /> 
      <Storyboard x:Key="slide"> 
       <DoubleAnimation From="0" To="{Binding Width, ElementName=canvas, Converter={StaticResource NegatingConverter}}" Duration="00:00:10" 
         Storyboard.TargetProperty="X" 
         Storyboard.TargetName="transferCurreny" 
         RepeatBehavior="Forever"/> 
      </Storyboard> 
     </StackPanel.Resources> 
     <StackPanel.RenderTransform> 
      <TranslateTransform x:Name="transferCurreny" X="0"/> 
     </StackPanel.RenderTransform> 
     <StackPanel.Triggers> 
      <EventTrigger RoutedEvent="StackPanel.Loaded"> 
       <BeginStoryboard Storyboard="{StaticResource slide}" /> 
      </EventTrigger> 
      <EventTrigger RoutedEvent="StackPanel.SizeChanged"> 
       <BeginStoryboard Storyboard="{StaticResource slide}" /> 
      </EventTrigger> 
     </StackPanel.Triggers> 
     <Canvas x:Name="canvas" Width="{Binding ActualWidth, ElementName=stack}"> 
      <TextBlock Text="StackOverflow" FontSize="25" x:Name="txtKron" Canvas.Left="0"/> 
      <TextBlock Text="{Binding Text, ElementName=txtKron}" FontSize="25" Canvas.Left="{Binding Width, ElementName=canvas}"/> 
     </Canvas> 
    </StackPanel> 
</Window> 

Ergebnis:

enter image description hereenter image description here

Edit: links nach rechts

<StackPanel Orientation="Horizontal" x:Name="stack"> 
     <StackPanel.Resources> 
      <local:NegatingConverter x:Key="NegatingConverter" /> 
      <Storyboard x:Key="slide"> 
       <DoubleAnimation From="0" To="{Binding Width, ElementName=canvas}" Duration="00:00:10" 
         Storyboard.TargetProperty="X" 
         Storyboard.TargetName="transferCurreny" 
         RepeatBehavior="Forever"/> 
      </Storyboard> 
     </StackPanel.Resources> 
     <StackPanel.RenderTransform> 
      <TranslateTransform x:Name="transferCurreny" X="0"/> 
     </StackPanel.RenderTransform> 
     <StackPanel.Triggers> 
      <EventTrigger RoutedEvent="StackPanel.Loaded"> 
       <BeginStoryboard Storyboard="{StaticResource slide}" /> 
      </EventTrigger> 
      <EventTrigger RoutedEvent="StackPanel.SizeChanged"> 
       <BeginStoryboard Storyboard="{StaticResource slide}" /> 
      </EventTrigger> 
     </StackPanel.Triggers> 
     <Canvas x:Name="canvas" Width="{Binding ActualWidth, ElementName=stack}"> 
      <TextBlock Text="StackOverflow" FontSize="25" x:Name="txtKron" Canvas.Left="0"/> 
      <TextBlock Text="{Binding Text, ElementName=txtKron}" FontSize="25" Canvas.Left="{Binding Width, ElementName=canvas, Converter={StaticResource NegatingConverter}}"/> 
     </Canvas> 
    </StackPanel> 
+0

Hallo Es ist wirklich toll. Ich arbeite daran, butom nach oben :), aber ich habe ein Problem dabei; wenn der erste Block nach oben (eigentlich ein Bild) ist es nach oben = 0 aber Bild ist fast top = 50, ich habe das nicht behoben. Vielen Dank! – meymetkaplan

+0

Es gibt ein Problem hier - Die Animation startet nicht. Ich habe es in dem dahinterliegenden Code behoben, indem ich ein Loaded Event hinzugefügt habe: Storyboard sb = (Storyboard) this.stack.FindResource ("slide"); stack.Dispatcher.BeginInvoke (DispatcherPriority.Loaded, neue Aktion (() => { sb.Begin(); })); –

+0

Wir können diesen gleichen Code auch zum Bild verwenden. Danke sa_ddam – Sagotharan

3

Der Code in der obigen Antwort erzeugt keinen kontinuierlichen Bildlauf. Hier ist der Code für das kontinuierliche sanfte Scrollen.

XAML:

<Window x:Class="Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <Canvas Margin="6,83,9,0" Name="ViewingBox" Background="YellowGreen" Height="35" VerticalAlignment="Top"> 
      <Label Canvas.Left="263" Canvas.Top="-2" Height="49" Name="BoxOne" FontSize="20">I need breakfast.</Label> 
      <Label Canvas.Left="263" Canvas.Top="-2" Height="49" HorizontalAlignment="Stretch" Name="BoxTwo" VerticalAlignment="Top" FontSize="20">You can have oranges and egg.</Label> 
     </Canvas> 
    </Grid> 
</Window> 

VB Code Behind:

Imports System.Windows.Media.Animation 

Public Enum Texts 
    BoxOne 
    BoxTwo 
End Enum 

Class Window1 
    Private dubAnim As New DoubleAnimation() 
    Private dubAnim2 As New DoubleAnimation() 
    Private NewsTimer As New Windows.Threading.DispatcherTimer() 
    Dim leadText As Texts = Texts.BoxOne 

    Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded 
     dubAnim.From = ViewingBox.ActualWidth 
     dubAnim.To = -BoxOne.ActualWidth 
     dubAnim.SpeedRatio = 0.05 
     AddHandler dubAnim.Completed, AddressOf dubAnim_Completed 
     Timeline.SetDesiredFrameRate(dubAnim, 320) 
     BoxOne.BeginAnimation(Canvas.LeftProperty, dubAnim) 

     dubAnim2.From = ViewingBox.ActualWidth 
     dubAnim2.To = -BoxTwo.ActualWidth 
     dubAnim2.SpeedRatio = 0.05 
     Timeline.SetDesiredFrameRate(dubAnim2, 320) 
     AddHandler dubAnim2.Completed, AddressOf dubAnim2_Completed 

     AddHandler NewsTimer.Tick, AddressOf NewsTimer_Tick 
     NewsTimer.Interval = New TimeSpan(0, 0, 0.9) 
     NewsTimer.Start() 
    End Sub 

    Private Sub NewsTimer_Tick(ByVal sender As Object, ByVal e As EventArgs) 
     Dim BoxOneLocation As Point = BoxOne.TranslatePoint(New Point(0, 0), ViewingBox) 
     Dim BoxTwoLocation As Point = BoxTwo.TranslatePoint(New Point(0, 0), ViewingBox) 

     If leadText = Texts.BoxOne Then 
      Dim loc As Double = BoxOneLocation.X + BoxOne.ActualWidth 
      If loc < ViewingBox.ActualWidth/1.5 Then 
       BoxTwo.BeginAnimation(Canvas.LeftProperty, dubAnim2) 
       NewsTimer.Stop() 
      End If 
     Else 
      Dim loc As Double = BoxTwoLocation.X + BoxTwo.ActualWidth 
      If loc < ViewingBox.ActualWidth/1.5 Then 
       BoxOne.BeginAnimation(Canvas.LeftProperty, dubAnim) 
       NewsTimer.Stop() 
      End If 
     End If 
    End Sub 

    Private Sub dubAnim_Completed(ByVal sender As Object, ByVal e As EventArgs) 
     leadText = Texts.BoxTwo 
     NewsTimer.Start() 
    End Sub 

    Private Sub dubAnim2_Completed(ByVal sender As Object, ByVal e As EventArgs) 
     leadText = Texts.BoxOne 
     NewsTimer.Start() 
    End Sub 
End Class 
+0

Schön. Funktioniert gut! –