2016-07-25 89 views
-1

我在下面給出的帶有XAML的窗口中實施了this question的解決方案。我試圖做一個標籤滾動字幕文本效果:WPF字幕文本動畫在其他控件中滾動

<Window x:Class="WpfMarqueeText.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:wpfMarqueeText="clr-namespace:WpfMarqueeText" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="200"/> 
      <RowDefinition Height="*"/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="500"/> 
      <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 

     <Grid Grid.Row="0" Grid.Column="0" Background="Aqua"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="200"/> 
       <ColumnDefinition Width="300"/> 
      </Grid.ColumnDefinitions> 

      <Ellipse Grid.Column="0" Margin="5,3,5,3" Fill="#b933ad"/> 
      <Label Grid.Column="0" Content="Z" Foreground="White" FontFamily="HelveticaBold" FontSize="150" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5,3,5,3"/> 

      <Grid Grid.Column="1"> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="*"/> 
       </Grid.RowDefinitions> 

       <Grid Grid.Row="0"> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto"/> 
         <RowDefinition Height="Auto"/> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="Auto"/> 
         <ColumnDefinition Width="*"/> 
        </Grid.ColumnDefinitions> 

        <Label Grid.Row="0" Grid.Column="0" Content="Some Info:" FontFamily="HelveticaBold" FontSize="18" FontWeight="Bold" Margin="5,3,5,3"/> 

        <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" x:Name="stack"> 
         <StackPanel.Resources> 
          <wpfMarqueeText: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}"> 
          <Label FontFamily="HelveticaBold" FontSize="18" Margin="5,3,5,3" x:Name="Label1" Content="Blah blah blah" Canvas.Left="0"/> 
          <Label Name="Label2" Content="{Binding Content, ElementName=Label1}" FontFamily="HelveticaBold" FontSize="18" Margin="5,3,5,3" Canvas.Left="{Binding ActualWidth, ElementName=stack}"/> 
         </Canvas> 

        </StackPanel> 
       </Grid> 
      </Grid> 
     </Grid> 
    </Grid> 
</Window> 

你也必須定義NegatingConverter類的代碼隱藏:

public class NegatingConverter : IValueConverter 
{ 

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

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

這將產生預期的效應,但是文動畫在滾動中看到下面的圖片(對不起,我沒有足夠的代表,發佈圖片)的其他用戶界面元素:

http://tinypic.com/r/df8zeu/9 http://tinypic.com/r/2inc3r/9

那麼,有什麼方法可以修復動畫,以便文本只在它所包含的網格列的邊界內或在標籤本身的邊界內滾動?謝謝你的幫助!

+0

http://www.codeproject.com/Articles/48267/Making-a-Simple-Marquee-Text-Control-Drip-Animatio應該會幫助你 – Akanksha

+0

真棒,感謝你發佈這個。我會盡力在我的項目中實現這一點。 – lunaa

回答

0

Akanksha爲響應我的OP鏈接的文章展示瞭如何創建一個產生乾淨的滾動文本效果的用戶控件。您還可以指定4個不同的滾動方向,左側< - >向右並向上< - >向下。我在這裏給我的實現爲他人:

XAML爲MarqueeTextUserControl:

<UserControl x:Class="AaronLuna.Common.UI.UserControls.MarqueeTextUserControl" 
     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" 
     mc:Ignorable="d" Loaded="UserControl_Loaded"> 

    <Canvas ClipToBounds="True" Name="CanvasMain"> 
     <TextBlock Name="TextBlockMain"/> 
    </Canvas> 

</UserControl> 

代碼MarqueeTextUserControl:

namespace AaronLuna.Common.UI.UserControls 
{   
    public partial class MarqueeTextUserControl 
    { 
     public MarqueeTextUserControl() 
     { 
      InitializeComponent(); 
      CanvasMain.Height = Height; 
      CanvasMain.Width = Width; 
     } 

     public ScrollDirection ScrollDirection { get; set; } 
     public double ScrollDurationInSeconds { get; set; } 
     public String Text { set { TextBlockMain.Text = value; }} 

     private void UserControl_Loaded(object sender, RoutedEventArgs e) 
     { 
      ScrollText(ScrollDirection); 
     } 

     public void ScrollText(ScrollDirection scrollDirection) 
     { 
      switch (scrollDirection) 
      { 
       case ScrollDirection.LeftToRight: 
        LeftToRightMarquee(); 
        break; 
       case ScrollDirection.RightToLeft: 
        RightToLeftMarquee(); 
        break; 
       case ScrollDirection.TopToBottom: 
        TopToBottomMarquee(); 
        break; 
       case ScrollDirection.BottomToTop: 
        BottomToTopMarquee(); 
        break; 
      } 
     } 

     private void LeftToRightMarquee() 
     { 
      double height = CanvasMain.ActualHeight - TextBlockMain.ActualHeight; 
      TextBlockMain.Margin = new Thickness(0, height/2, 0, 0); 

      var doubleAnimation = new DoubleAnimation 
      { 
       From = -TextBlockMain.ActualWidth, 
       To = CanvasMain.ActualWidth, 
       RepeatBehavior = RepeatBehavior.Forever, 
       Duration = new Duration(TimeSpan.FromSeconds(ScrollDurationInSeconds)) 
      }; 

      TextBlockMain.BeginAnimation(Canvas.LeftProperty, doubleAnimation); 
     } 

     private void RightToLeftMarquee() 
     { 
      double height = CanvasMain.ActualHeight - TextBlockMain.ActualHeight; 
      TextBlockMain.Margin = new Thickness(0, height/2, 0, 0); 

      var doubleAnimation = new DoubleAnimation 
      { 
       From = -TextBlockMain.ActualWidth, 
       To = CanvasMain.ActualWidth, 
       RepeatBehavior = RepeatBehavior.Forever, 
       Duration = new Duration(TimeSpan.FromSeconds(ScrollDurationInSeconds)) 
      }; 

      TextBlockMain.BeginAnimation(Canvas.RightProperty, doubleAnimation); 
     } 

     private void TopToBottomMarquee() 
     { 
      double width = CanvasMain.ActualWidth - TextBlockMain.ActualWidth; 
      TextBlockMain.Margin = new Thickness(width/2, 0, 0, 0); 

      var doubleAnimation = new DoubleAnimation 
      { 
       From = -TextBlockMain.ActualHeight, 
       To = CanvasMain.ActualHeight, 
       RepeatBehavior = RepeatBehavior.Forever, 
       Duration = new Duration(TimeSpan.FromSeconds(ScrollDurationInSeconds)) 
      }; 

      TextBlockMain.BeginAnimation(Canvas.TopProperty, doubleAnimation); 
     } 

     private void BottomToTopMarquee() 
     { 
      double width = CanvasMain.ActualWidth - TextBlockMain.ActualWidth; 
      TextBlockMain.Margin = new Thickness(width/2, 0, 0, 0); 

      var doubleAnimation = new DoubleAnimation 
      { 
       From = -TextBlockMain.ActualHeight, 
       To = CanvasMain.ActualHeight, 
       RepeatBehavior = RepeatBehavior.Forever, 
       Duration = new Duration(TimeSpan.FromSeconds(ScrollDurationInSeconds)) 
      }; 

      TextBlockMain.BeginAnimation(Canvas.BottomProperty, doubleAnimation); 
     } 
    } 

    public enum ScrollDirection 
    { 
     LeftToRight, 
     RightToLeft, 
     TopToBottom, 
     BottomToTop 
    } 
} 

客戶XAML:

<UserControl x:Class="MarqueeTextExampleUserControl" 
     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:userControls="clr-namespace:AaronLuna.Common.UI.UserControls;assembly=AaronLuna.Common" 
     mc:Ignorable="d"> 

    <DockPanel> 
     <Label Content="Some Info:"/> 
     <userControls:MarqueeTextUserControl x:Name="MarqueeTextBlock"/> 
    </DockPanel> 

</UserControl> 

客戶端代碼:

MarqueeTextBlock.Text = "Blah blah blah"; 
MarqueeTextBlock.ScrollDirection = ScrollDirection.RightToLeft; 
MarqueeTextBlock.ScrollDurationInSeconds = 10; 
0

這是一個快速和骯髒的解決方案:

更改Label

<Label Grid.Row="0" Grid.Column="0" Content="Some Info:" FontFamily="HelveticaBold" FontSize="18" FontWeight="Bold" Margin="5,3,5,3" Panel.ZIndex="99" Background="Aqua"/> 

Panel.ZIndex帶來Label前面。並使Background不透明給出所需的外觀。邊界仍然不完美,但是這應該給你一個關於如何處理圖層的線索

+0

謝謝!我想嘗試類似的東西,但將ZIndex應用於錯誤的XAML元素。 – lunaa