You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WPF中使用DoubleAnimation实现FontStretch属性动画?

如何为FontStretch属性创建动画?

你这段代码的问题很明显——FontStretch是FontStretch类型,不是Double,所以用DoubleAnimation直接动画它肯定会失效,WPF根本没法把Double值转换成FontStretch。下面给你两种实用的解决方案,选哪种看你的需求:

方案一:用ObjectAnimationUsingKeyFrames实现平滑过渡(推荐)

这种方法不用写额外的C#代码,直接在XAML里搞定,而且能实现平滑的字体拉伸效果。核心是利用WPF对FontStretch类型的插值支持,用LinearObjectKeyFrame来做关键帧动画:

<Style TargetType="TextBlock" x:Key="TextBlockStyle">
    <!-- 默认字体拉伸为Normal -->
    <Setter Property="FontStretch" Value="{x:Static FontStretches.Normal}"/>
    <Style.Triggers>
        <!-- 鼠标进入时,0.3秒内从Normal变为UltraCondensed -->
        <EventTrigger RoutedEvent="MouseEnter">
            <BeginStoryboard>
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetProperty="FontStretch"
                        Duration="0:0:0.3">
                        <LinearObjectKeyFrame KeyTime="0:0:0" Value="{x:Static FontStretches.Normal}"/>
                        <LinearObjectKeyFrame KeyTime="0:0:0.3" Value="{x:Static FontStretches.UltraCondensed}"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <!-- 鼠标离开时,还原回Normal -->
        <EventTrigger RoutedEvent="MouseLeave">
            <BeginStoryboard>
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetProperty="FontStretch"
                        Duration="0:0:0.3">
                        <LinearObjectKeyFrame KeyTime="0:0:0" Value="{x:Static FontStretches.UltraCondensed}"/>
                        <LinearObjectKeyFrame KeyTime="0:0:0.3" Value="{x:Static FontStretches.Normal}"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Style.Triggers>
</Style>

另外提一句:你原来的EventTrigger写的是Button.MouseEnter,但这个Style是给TextBlock用的,改成MouseEnter就够了,WPF会自动匹配目标控件的事件。

方案二:用DoubleAnimation+转换器(自定义数值场景)

如果需要更精细控制拉伸的数值(比如不是用预定义的UltraCondensed,而是自定义某个拉伸值),可以用DoubleAnimation配合转换器。步骤如下:

第一步:创建转换器类

在你的项目里加一个C#类,把Double值转换成FontStretch:

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace YourNamespace
{
    public class DoubleToFontStretchConverter : IValueConverter
    {
        // 把Double转换成FontStretch
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is double numericValue)
            {
                // OpenType拉伸值范围是1-1000,Normal对应100,UltraCondensed对应50
                return FontStretch.FromOpenTypeStretch((int)numericValue);
            }
            return FontStretches.Normal;
        }

        // 把FontStretch转换成Double(动画需要双向绑定)
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is FontStretch stretch)
            {
                return stretch.NumericValue;
            }
            return 100.0;
        }
    }
}

第二步:在XAML里使用转换器

用TextBlock的Tag属性作为中间值,通过转换器绑定到FontStretch,然后动画Tag的Double值:

<Window.Resources>
    <!-- 引用转换器 -->
    <local:DoubleToFontStretchConverter x:Key="DoubleToFontStretchConverter"/>
    
    <Style TargetType="TextBlock" x:Key="TextBlockStyle">
        <Setter Property="FontStretch" 
                Value="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Converter={StaticResource DoubleToFontStretchConverter}}"/>
        <!-- 默认Tag值为100(对应Normal) -->
        <Setter Property="Tag" Value="100"/>
        
        <Style.Triggers>
            <EventTrigger RoutedEvent="MouseEnter">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation 
                            Storyboard.TargetProperty="Tag"
                            From="100"
                            To="50" <!-- 对应UltraCondensed -->
                            Duration="0:0:0.3"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
            <EventTrigger RoutedEvent="MouseLeave">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation 
                            Storyboard.TargetProperty="Tag"
                            From="50"
                            To="100"
                            Duration="0:0:0.3"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

两种方案里,第一种更简单直接,适合大多数场景;第二种适合需要自定义拉伸程度的情况,比如动画到一个预定义值之外的拉伸效果。

内容的提问来源于stack exchange,提问作者Imathie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:46:11