最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于WPF實現跳動的字符效果

 更新時間:2023年08月10日 08:43:18   作者:czwy  
這篇文章主要和大家介紹一個好玩但實際作用可能不太大的動畫效果:跳動的字符,本文將利用WPF實現這一效果,感興趣的小伙伴可以學習一下

本文將介紹一個好玩但實際作用可能不太大的動畫效果:跳動的字符。為了提高動畫效果的可重用性以及調用的靈活性,通過Behavior實現跳動的字符動畫。先看下效果:

技術要點與實現

通過TextEffectPositionStartPositionCount屬性控制應用動畫效果的子字符串的起始位置以及長度,同時使用TranslateTransform設置字符縱坐標的移動變換,以實現跳動的效果。主要步驟如下:

  • 在OnAttached方法中,注冊Loaded事件,在Load事件中為TextBlock添加TextEffect效果,其中PositionCount設置為1,每次只跳動一個字符。
  • 添加啟動動畫效果的BeginEffect方法,并創(chuàng)建控制子字符縱向移動變換的線性動畫。然后根據字符串(剔除空字符)的長度n,創(chuàng)建n個關鍵幀,每個關鍵幀中把PositionStart設置為要跳動的字符在字符串中的索引
  • 在開啟動畫屬性IsEnabled=trueTextBlock內容變化時,啟動動畫效果

在創(chuàng)建關鍵幀設置跳動字符位置時剔除了空字符,是為了是動畫效果顯得連貫

public class DanceCharEffectBehavior : Behavior<TextBlock>
    {
        private TextEffect _textEffect;
        private string _textEffectName;
        private TranslateTransform _translateTransform = null;
        private string _translateTransformName;
        private Storyboard _storyboard;
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.Loaded += AssociatedObject_Loaded;
            this.AssociatedObject.Unloaded += AssociatedObject_Unloaded;
            this.AssociatedObject.IsVisibleChanged += AssociatedObject_IsVisibleChanged;
            BindingOperations.SetBinding(this, DanceCharEffectBehavior.InternalTextProperty, new Binding("Text") { Source = this.AssociatedObject });
        }
        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.Loaded -= AssociatedObject_Loaded;
            this.AssociatedObject.Unloaded -= AssociatedObject_Unloaded;
            this.AssociatedObject.IsVisibleChanged -= AssociatedObject_IsVisibleChanged;
            this.ClearValue(DanceCharEffectBehavior.InternalTextProperty);
            if (_storyboard != null)
            {
                _storyboard.Remove(this.AssociatedObject);
                _storyboard.Children.Clear();
            }
            if (_textEffect != null)
                this.AssociatedObject.TextEffects.Remove(_textEffect);
        }
        private void AssociatedObject_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.NewValue == false)
            {
                if (_storyboard != null)
                    _storyboard.Stop(this.AssociatedObject);
            }
            else
            {
                BeginEffect(this.AssociatedObject.Text);
            }
        }
        private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
            if (_textEffect == null)
            {
                this.AssociatedObject.TextEffects.Add(_textEffect = new TextEffect()
                {
                    PositionCount = 1,
                    Transform = _translateTransform = new TranslateTransform(),
                });
                NameScope.SetNameScope(this.AssociatedObject, new NameScope());
                this.AssociatedObject.RegisterName(_textEffectName = "n" + Guid.NewGuid().ToString("N"), _textEffect);
                this.AssociatedObject.RegisterName(_translateTransformName = "n" + Guid.NewGuid().ToString("N"), _translateTransform);
                if (IsEnabled)
                    BeginEffect(this.AssociatedObject.Text);
            }
        }
        private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
        {
            StopEffect();
        }
        private void SetEffect(string text)
        {
            if (string.IsNullOrEmpty(text) || this.AssociatedObject.IsLoaded == false)
            {
                StopEffect();
                return;
            }
            BeginEffect(text);
        }
        private void StopEffect()
        {
            if (_storyboard != null)
            {
                _storyboard.Stop(this.AssociatedObject);
            }
        }
        private void BeginEffect(string text)
        {
            StopEffect();
            int textLength = text.Length;
            if (textLength < 1 || _translateTransformName == null || IsEnabled == false) return;
            if (_storyboard == null)
                _storyboard = new Storyboard();
            double duration = 0.5d;
            DoubleAnimation da = new DoubleAnimation();
            Storyboard.SetTargetName(da, _translateTransformName);
            Storyboard.SetTargetProperty(da, new PropertyPath(TranslateTransform.YProperty));
            da.From = 0d;
            da.To = 10d;
            da.Duration = TimeSpan.FromSeconds(duration / 2d);
            da.RepeatBehavior = RepeatBehavior.Forever;
            da.AutoReverse = true;
            char emptyChar = ' ';
            List<int> lsb = new List<int>();
            for (int i = 0; i < textLength; ++i)
            {
                if (text[i] != emptyChar)
                {
                    lsb.Add(i);
                }
            }
            Int32AnimationUsingKeyFrames frames = new Int32AnimationUsingKeyFrames();
            Storyboard.SetTargetName(frames, _textEffectName);
            Storyboard.SetTargetProperty(frames, new PropertyPath(TextEffect.PositionStartProperty));
            frames.Duration = TimeSpan.FromSeconds((lsb.Count) * duration);
            frames.RepeatBehavior = RepeatBehavior.Forever;
            frames.AutoReverse = true;
            int ii = 0;
            foreach (int index in lsb)
            {
                frames.KeyFrames.Add(new DiscreteInt32KeyFrame()
                {
                    Value = index,
                    KeyTime = TimeSpan.FromSeconds(ii * duration),
                });
                ++ii;
            }
            _storyboard.Children.Add(da);
            _storyboard.Children.Add(frames);
            _storyboard.Begin(this.AssociatedObject, true);
        }
        private string InternalText
        {
            get { return (string)GetValue(InternalTextProperty); }
            set { SetValue(InternalTextProperty, value); }
        }
        private static readonly DependencyProperty InternalTextProperty =
        DependencyProperty.Register("InternalText", typeof(string), typeof(DanceCharEffectBehavior),
        new PropertyMetadata(OnInternalTextChanged));
        private static void OnInternalTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var source = d as DanceCharEffectBehavior;
            if (source._storyboard != null)
            {
                source._storyboard.Stop(source.AssociatedObject);
                source._storyboard.Children.Clear();
            }
            source.SetEffect(e.NewValue == null ? string.Empty : e.NewValue.ToString());
        }
        public bool IsEnabled
        {
            get { return (bool)GetValue(IsEnabledProperty); }
            set { SetValue(IsEnabledProperty, value); }
        }
        public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.Register("IsEnabled", typeof(bool), typeof(DanceCharEffectBehavior), new PropertyMetadata(true, (d, e) =>
            {
                bool b = (bool)e.NewValue;
                var source = d as DanceCharEffectBehavior;
                source.SetEffect(source.InternalText);
            }));
    }

調用的時候只需要在TextBlock添加Behavior即可,代碼如下

<TextBlock FontSize="20" Text="Hello">
    <i:Interaction.Behaviors>
        <local:DanceCharEffectBehavior x:Name="titleEffect" IsEnabled="True" />
    </i:Interaction.Behaviors>
</TextBlock>

結尾

本例中還有許多可以完善的地方,比如字符跳動的幅度可以根據實際的FontSize來設置,或者增加依賴屬性來控制;動畫是否倒退播放,是否循環(huán)播放,以及動畫的速度都可以通過增加依賴屬性在調用時靈活設置。

到此這篇關于基于WPF實現跳動的字符效果的文章就介紹到這了,更多相關WPF字符跳動效果內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C#?調用外部exe的三種方式

    C#?調用外部exe的三種方式

    調用外部exe是常用的功能,本文主要介紹了C#?調用外部exe的三種方式,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2024-04-04
  • c#讀取excel方法實例分析

    c#讀取excel方法實例分析

    這篇文章主要介紹了c#讀取excel方法,實例分析了C#讀取excel文件的原理與相關技巧,需要的朋友可以參考下
    2015-06-06
  • C#將指定目錄所有文件名轉換成小寫的方法

    C#將指定目錄所有文件名轉換成小寫的方法

    這篇文章主要介紹了C#將指定目錄所有文件名轉換成小寫的方法,涉及C#中目錄的遍歷及filename.ToLowerInvariant方法的使用技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • C#實現windows form限制文本框輸入的方法

    C#實現windows form限制文本框輸入的方法

    這篇文章主要介紹了C#實現windows form限制文本框輸入的方法,涉及C#限制文本框輸入的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • 在C#中實現文本與Word文檔互相轉換的操作步驟

    在C#中實現文本與Word文檔互相轉換的操作步驟

    在現代軟件開發(fā)中,處理文檔內容是一個非常常見的需求,無論是生成報告、存儲日志,還是處理用戶輸入,開發(fā)者都可能需要在純文本與 Word 文檔之間進行轉換,所以本文給大家介紹了如何在 C# 中將文本轉換為 Word 以及將 Word 轉換為文本,需要的朋友可以參考下
    2025-09-09
  • WPF中不規(guī)則窗體與WindowsFormsHost控件兼容問題的解決方法

    WPF中不規(guī)則窗體與WindowsFormsHost控件兼容問題的解決方法

    這篇文章主要介紹了WPF中不規(guī)則窗體與WindowsFormsHost控件兼容問題的解決方法,對比以往的解決方案,給出了一個具有普遍性的技巧,具有一定的借鑒價值,需要的朋友可以參考下
    2014-11-11
  • C#使用SqlServer作為日志數據庫的設計與實現

    C#使用SqlServer作為日志數據庫的設計與實現

    這篇文章主要給大家介紹了關于C#使用SqlServer作為日志數據庫的設計與實現的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • C#.NET ObjectPool 對象復用、池化策略與使用邊界

    C#.NET ObjectPool 對象復用、池化策略與使用邊界

    本文主要介紹了C#.NET ObjectPool 對象復用、池化策略與使用邊界,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-06-06
  • C#使用Monitor類實現線程同步

    C#使用Monitor類實現線程同步

    這篇文章介紹了C#使用Monitor類實現線程同步的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • 使用GetInvalidFileNameCharts生成文件名

    使用GetInvalidFileNameCharts生成文件名

    這篇文章主要介紹了一個很實用的函數Path.GetInvalidFileNameCharts(),他可以很方便的生成一個有效的文件名稱
    2014-01-01

最新評論

获嘉县| 永康市| 鹤岗市| 眉山市| 沅陵县| 两当县| 武安市| 红安县| 台南县| 福海县| 北海市| 苗栗市| 武城县| 古蔺县| 丘北县| 长丰县| 来宾市| 石景山区| 尉氏县| 灯塔市| 察雅县| 德格县| 永嘉县| 乌兰浩特市| 靖宇县| 常德市| 汝阳县| 安仁县| 洛阳市| 兰西县| 阿拉善右旗| 海伦市| 丰原市| 安阳市| 新巴尔虎左旗| 凌云县| 南召县| 微博| 云龙县| 茂名市| 海晏县|