上图中的两个动画,一个文字直接变粗,一个渐渐变粗,我觉得后者会更有趣。但普通的字体可达不到这种效果,例如微软雅黑,无论怎么调整它的 FontWeight,实际上它也只有三种粗细:
这时候我们需要可变字体,可变字体(Variable fonts)是OpenType字体规范上的演进,它允许将同一字体的多个变体统合进单独的字体文件中。从而无需再将不同字宽、字重或不同样式的字体分割成不同的字体文件。你只需通过CSS与一行@font-face
引用,即可获取包含在这个单一文件中的各种字体变体。具体来说请参考这篇文档:
https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
简单来说,可变字体是可以实现随意改变字重,满足我需求的方案。而要实现随意改变中文文字的字重,思源黑体 是其中一个不错的选择:
2. 假装可变字体可是我不知道怎么在 WPF 里用可变字体,而且为了一个小小按钮的小小动画,居然要添加一个几十兆大小的字体,这性价比实在低,低到不能接受。其实我最初的目标只是让文字慢慢变粗,不一定需要让文字变成粗体,用我上一篇文章提到的 实现文字描边 也可以做到。文字描边的基本原理是使用 FormattedText
的 BuildGeometry
拿到 Geometry,然后通过 Shape 画出来,最后通过 Stroke, StrokeThickness 控制文字边框的颜色和粗细。核心代码如下:
var formattedText = new FormattedText(
Text,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(FontFamily, FontStyle, FontWeight, FontStretch), FontSize, Brushes.Black, 100);
_height = formattedText.Height;
_width = formattedText.Width;
_textGeometry = formattedText.BuildGeometry(new Point());
如果加大 StrokeThickness 可以让文字的边框变得很粗,效果如下:
如果将文字的文字和边框设置为同一个颜色呢?改变 StrokeThickness 看起来就像改变 FontWeight,这就实现了我想要的效果:
当然,用这种方式假装的可变字体的字形和原本的字形会有差别,但用在局部的动画没什么大的问题。如果用得好,可以做不少有趣的 UI ,例如这样:
从上面的想法延申一下,反过来从粗变细,可以玩另一种动画。如果找一个超细的字体,例如这个:
将它的 StrokeThickness 由一个很大的值渐变成 0,可以做到下面这种动画:
3. 最后这篇文章其实没介绍什么代码技巧,只是从上一篇文章 实现文字描边 延申出来的玩法。更多关于 WPF 的设计和动画技巧,可以参考我这个项目:
https://github.com/DinoChan/wpf_design_and_animation_lab