代码之家  ›  专栏  ›  技术社区  ›  Nahuel Ovejero

将textblock从一个点设置为另一个点的动画

  •  0
  • Nahuel Ovejero  · 技术社区  · 7 年前

    我想将TextBlock元素从屏幕的右侧部分移到左侧(就像新闻中的文本)。

    <Canvas>
        <!-- Offset the text using a TranslateTransform. -->
        <TextBlock Text="{Binding Picker}" VerticalAlignment="Bottom" Margin="0,0,0,0" TextWrapping="Wrap" FontSize="33" >
             <TextBlock.RenderTransform>
                  <TranslateTransform X="2" Y="2" />
             </TextBlock.RenderTransform>
        </TextBlock>
    
        <TextBlock Text="{Binding Picker}" VerticalAlignment="Bottom" Margin="0,0,0,0" TextWrapping="Wrap" FontSize="33" />
    </Canvas>
    

    我找不到一个属性/操作来实现这一点,我对UWP真的是个新手,而且我知道我拥有的XAML不会做这样的事情。 它只会像阴影效果一样放置另一个文本块。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Romasz    7 年前

    下面是一个可能的解决方案-通过使用一些 视觉状态 :

    <Canvas>
        <Canvas.Resources>
            <local:InvertBooleanConverter x:Key="InvBoolConverter"/>
        </Canvas.Resources>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="States">
                <VisualState x:Name="Left">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="myTextBlock" Storyboard.TargetProperty="(Canvas.Left)" To="0" Duration="0:0:1"/>
                    </Storyboard>
                    <VisualState.StateTriggers>
                        <StateTrigger IsActive="{Binding ElementName=myButton, Path=IsOn, Converter={StaticResource InvBoolConverter}}"/>
                    </VisualState.StateTriggers>
                </VisualState>
                <VisualState x:Name="Right">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="myTextBlock" Storyboard.TargetProperty="(Canvas.Left)" To="200" Duration="0:0:1"/>
                    </Storyboard>
                    <VisualState.StateTriggers>
                        <StateTrigger IsActive="{Binding ElementName=myButton, Path=IsOn}"/>
                    </VisualState.StateTriggers>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <!-- Offset the text using a TranslateTransform. -->
        <TextBlock x:Name="myTextBlock" Text="Test" VerticalAlignment="Bottom" Margin="0,0,0,0" TextWrapping="Wrap" FontSize="33" />
        <ToggleSwitch  x:Name="myButton" Margin="0,50,0,0" OffContent="Left" OnContent="Right"/>
    </Canvas>
    

    和后面的转换器:

    public class InvertBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language) => !(bool)value;
        public object ConvertBack(object value, Type targetType, object parameter, string language) => throw new NotImplementedException();
    }
    
        2
  •  2
  •   thezapper    7 年前

    我在我的一个项目中创建了一个模板控件,当文本大于矩形本身时,文本会自动移动。。。也许这会帮助你或者给你一个主意

    public enum MarqueeScrollingDirection
    {
        FromLeft,
        FromRight,
        FromTop,
        FromBottom,
        None,
    }
    
    public sealed class MarqueeUserControl : Control
    {
        public static readonly DependencyProperty MarqueeDirectionProperty = DependencyProperty.Register(nameof(MarqueeDirection), typeof(MarqueeScrollingDirection), typeof(MarqueeUserControl),new PropertyMetadata(MarqueeScrollingDirection.None));
        public MarqueeScrollingDirection MarqueeDirection
        {
            get { return (MarqueeScrollingDirection)GetValue(MarqueeDirectionProperty); }
            set { SetValue(MarqueeDirectionProperty, value); }
        }
    
        public static readonly DependencyProperty MarqueeTextProperty = DependencyProperty.Register(nameof(MarqueeText), typeof(string), typeof(MarqueeUserControl), new PropertyMetadata(string.Empty));
        public string MarqueeText
        {
            get { return (string)GetValue(MarqueeTextProperty); }
            set { SetValue(MarqueeTextProperty, value); }
        }
    
        public MarqueeUserControl()
        {
            this.DefaultStyleKey = typeof(MarqueeUserControl);
            this.SizeChanged += MarqueeUserControl_SizeChanged;
        }
    
        private Canvas ContentCanvas;
        private TextBlock MarqueeTextBlock;
        private Storyboard storyboard;
        private DoubleAnimation doubleAnimation;
    
        protected override void OnApplyTemplate()
        {
            MarqueeTextBlock = (TextBlock)GetTemplateChild(nameof(MarqueeTextBlock));
            ContentCanvas = (Canvas)GetTemplateChild(nameof(ContentCanvas));
    
            if (MarqueeDirection != MarqueeScrollingDirection.None)
            {
                MarqueeTextBlock.SizeChanged += MarqueeUserControl_SizeChanged;
    
                storyboard = new Storyboard();
                doubleAnimation = new DoubleAnimation();
    
                doubleAnimation.AutoReverse = true;
                doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
    
                if (MarqueeDirection == MarqueeScrollingDirection.FromLeft || MarqueeDirection == MarqueeScrollingDirection.FromRight)
                {
                    Storyboard.SetTargetProperty(doubleAnimation, "(UIElement.RenderTransform).(TranslateTransform.X)");
                }
                if (MarqueeDirection == MarqueeScrollingDirection.FromTop || MarqueeDirection == MarqueeScrollingDirection.FromBottom)
                {
                    Storyboard.SetTargetProperty(doubleAnimation, "(UIElement.RenderTransform).(TranslateTransform.Y)");
                }
    
                Storyboard.SetTarget(doubleAnimation, MarqueeTextBlock);
            }
            else
            {
                (MarqueeTextBlock.RenderTransform as TranslateTransform).X = (ContentCanvas.ActualWidth - MarqueeTextBlock.ActualWidth) / 2;
            }
        }
    
        private void MarqueeUserControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (MarqueeDirection != MarqueeScrollingDirection.None)
            {
                bool play = false;
    
                RectangleGeometry rectangleGeometry = new RectangleGeometry()
                {
                    Rect = new Rect(0, 0, ContentCanvas.ActualWidth, ContentCanvas.ActualHeight)
                };
                ContentCanvas.Clip = rectangleGeometry;
    
                storyboard.Stop();
                storyboard.Children.Clear();
    
                switch (MarqueeDirection)
                {
                    case MarqueeScrollingDirection.FromLeft:
                        doubleAnimation.From = MarqueeTextBlock.ActualWidth > ContentCanvas.ActualWidth ? ContentCanvas.ActualWidth - MarqueeTextBlock.ActualWidth : 0;
                        doubleAnimation.To = 0;
                        doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(MarqueeTextBlock.ActualWidth > ContentCanvas.ActualWidth ? ((MarqueeTextBlock.ActualWidth - ContentCanvas.ActualWidth) / 10) +1 : 0));
    
                        play = MarqueeTextBlock.ActualWidth > ContentCanvas.ActualWidth;
                        break;
                    case MarqueeScrollingDirection.FromRight:
                        doubleAnimation.From = 0;
                        doubleAnimation.To = MarqueeTextBlock.ActualWidth > ContentCanvas.ActualWidth ? ContentCanvas.ActualWidth - MarqueeTextBlock.ActualWidth : 0;
                        doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(MarqueeTextBlock.ActualWidth > ContentCanvas.ActualWidth ? ((MarqueeTextBlock.ActualWidth - ContentCanvas.ActualWidth) / 10) + 1 : 0));
    
                        play = MarqueeTextBlock.ActualWidth > ContentCanvas.ActualWidth;
                        break;
                    case MarqueeScrollingDirection.FromTop:
    
                        play = MarqueeTextBlock.ActualWidth > ContentCanvas.ActualWidth;
                        break;
                    case MarqueeScrollingDirection.FromBottom:
    
                        play = MarqueeTextBlock.ActualWidth > ContentCanvas.ActualWidth;
                        break;
                    case MarqueeScrollingDirection.None:
    
                        play = false;
                        break;
                    default:
                        break;
                }
    
                if (play)
                {
                    storyboard.Children.Add(doubleAnimation);
                    storyboard.Begin();
                }
                else
                {
                    (MarqueeTextBlock.RenderTransform as TranslateTransform).X = (ContentCanvas.ActualWidth - MarqueeTextBlock.ActualWidth) / 2;
                }
            }
        }
    }
    

    和通用。xaml

    <ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:uc="using:roomZone.UserControls">
    
    <Style TargetType="uc:MarqueeUserControl" >
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="uc:MarqueeUserControl">
                    <RelativePanel x:Name="RootElement"
                          Background="{TemplateBinding Background}"
                          BorderBrush="{TemplateBinding BorderBrush}"
                          BorderThickness="{TemplateBinding BorderThickness}" >
                        <Canvas x:Name="ContentCanvas" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignTopWithPanel="True" RelativePanel.AlignBottomWithPanel="True"
                                MinWidth="100" MinHeight="16" >
                            <Border VerticalAlignment="Center" >
                                <TextBlock x:Name="MarqueeTextBlock"
                                           HorizontalAlignment="Left"
                                           VerticalAlignment="Center"
                                           Text="{TemplateBinding MarqueeText}"
                                           Foreground="{TemplateBinding Foreground}"
                                           FontFamily="{TemplateBinding FontFamily}"
                                           FontSize="{TemplateBinding FontSize}"
                                           FontStyle="{TemplateBinding FontStyle}"
                                           FontStretch="{TemplateBinding FontStretch}"
                                           FontWeight="{TemplateBinding FontWeight}" >
                                    <TextBlock.RenderTransform>
                                        <TranslateTransform />
                                    </TextBlock.RenderTransform>
                                </TextBlock>
                            </Border>
                        </Canvas>
                    </RelativePanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    </ResourceDictionary>