WPF开发者QQ群: 340500857 | 微信群 -> 进入公众号主页 加入组织
前言
效果仿照 CSS聚光灯效果
实现思路:
1. 设置底部Canvas背景色 #222222 。
2. 准备两个 TextBlock 控件在同一位置。
3. 设置底部 TextBlock 字体颜色Foreground="#323232"。
4. 设置上层 TextBlock 字体颜色为渐变色。
5. 设置上层 TextBlock.Clip 针对 EllipseGeometry 做 TranslateTransform 的X轴移动动画。
6. DoubleAnimation的To值为上层或者下层控件的ActualWidth获取此元素的呈现宽度。
7. 故事板初始化 Storyboard RepeatBehavior =RepeatBehavior.Forever,AutoReverse = true。
效果预览(更多效果请下载源码体验)
一、SpotLight.cs 代码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; namespace WPFDevelopers.Controls { [TemplatePart(Name = TextBlockBottomTemplateName, Type = typeof(TextBlock))] [TemplatePart(Name = TextBlockTopTemplateName, Type = typeof(TextBlock))] [TemplatePart(Name = EllipseGeometryTemplateName, Type = typeof(EllipseGeometry))] public class SpotLight : Control { private const string TextBlockBottomTemplateName = "PART_TextBlockBottom"; private const string TextBlockTopTemplateName = "PART_TextBlockTop"; private const string EllipseGeometryTemplateName = "PART_EllipseGeometry"; private TextBlock _textBlockBottom, _textBlockTop; private EllipseGeometry _ellipseGeometry; public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(SpotLight), new PropertyMetadata("WPFDevelopers")); static SpotLight() { DefaultStyleKeyProperty.OverrideMetadata(typeof(SpotLight), new FrameworkPropertyMetadata(typeof(SpotLight))); } public SpotLight() { this.Loaded += SpotLight_Loaded; } private void SpotLight_Loaded(object sender, RoutedEventArgs e) { Canvas.SetLeft(_textBlockBottom, ActualWidth / 3); Canvas.SetTop(_textBlockBottom, ActualHeight / 3); Canvas.SetLeft(_textBlockTop, ActualWidth / 3); Canvas.SetTop(_textBlockTop, ActualHeight / 3); } public override void OnApplyTemplate() { base.OnApplyTemplate(); _textBlockBottom = GetTemplateChild(TextBlockBottomTemplateName) as TextBlock; _textBlockTop = GetTemplateChild(TextBlockTopTemplateName) as TextBlock; _ellipseGeometry = GetTemplateChild(EllipseGeometryTemplateName) as EllipseGeometry; var center = new Point(FontSize/2, FontSize/2); _ellipseGeometry.RadiusX = FontSize; _ellipseGeometry.RadiusY = FontSize; _ellipseGeometry.Center = center; if (_textBlockBottom != null && _textBlockTop != null && _ellipseGeometry != null) _textBlockTop.Loaded += _textBlockTop_Loaded; } private void _textBlockTop_Loaded(object sender, RoutedEventArgs e) { var doubleAnimation = new DoubleAnimation { To = _textBlockTop.ActualWidth, Duration = TimeSpan.FromSeconds(3) }; Storyboard.SetTarget(doubleAnimation, _textBlockTop); Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(UIElement.Clip).(EllipseGeometry.Transform).(TranslateTransform.X)")); var storyboard = new Storyboard { RepeatBehavior = RepeatBehavior.Forever, AutoReverse = true }; storyboard.Children.Add(doubleAnimation); storyboard.Completed += (s, q) => { }; storyboard.Begin(); } } }
二、SpotLight.xaml 代码如下
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:WPFDevelopers.Controls"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Basic/ControlBasic.xaml"/> </ResourceDictionary.MergedDictionaries> <Style TargetType="{x:Type controls:SpotLight}" BasedOn="{StaticResource ControlBasicStyle}"> <Setter Property="Background" Value="#222222"/> <Setter Property="FontSize" Value="60"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type controls:SpotLight}"> <Canvas x:Name="PART_Canvas" Background="{TemplateBinding Background}"> <TextBlock x:Name="PART_TextBlockBottom" Text="{TemplateBinding Text}" FontSize="{TemplateBinding FontSize}" FontFamily="Arial Black" FontWeight="Bold" Foreground="#323232"/> <TextBlock x:Name="PART_TextBlockTop" Text="{TemplateBinding Text}" FontSize="{TemplateBinding FontSize}" FontFamily="Arial Black" FontWeight="Bold"> <TextBlock.Foreground> <LinearGradientBrush EndPoint="1,1" MappingMode="RelativeToBoundingBox" StartPoint="0,0"> <GradientStop Color="#FF9C1031" Offset="0.1"/> <GradientStop Color="#FFBE0E20" Offset="0.2"/> <GradientStop Color="#FF9C12AC" Offset="0.7"/> <GradientStop Color="#FF0A8DC3" Offset="0.8"/> <GradientStop Color="#FF1AEBCC" Offset="1"/> </LinearGradientBrush> </TextBlock.Foreground> <TextBlock.Clip> <EllipseGeometry x:Name="PART_EllipseGeometry"> <EllipseGeometry.Transform> <TranslateTransform/> </EllipseGeometry.Transform> </EllipseGeometry> </TextBlock.Clip> </TextBlock> </Canvas> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
三、SpotLightExample.Xaml 代码如下
<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.SpotLightExample" 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:local="clr-namespace:WPFDevelopers.Samples.ExampleViews" xmlns:wpfdev="https://github.com/yanjinhuagood/WPFDevelopers" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <UniformGrid Rows="2"> <wpfdev:SpotLight FontSize="50" Text="YanJinHua"/> <wpfdev:SpotLight/> </UniformGrid> </UserControl>
更多教程欢迎关注微信公众号:
WPF开发者QQ群: 340500857
blogs: https://www.cnblogs.com/yanjinhua/p/14345136.html
源码Github:https://github.com/yanjinhuagood/WPFDevelopers.git
gitee:https://gitee.com/yanjinhua/WPFDevelopers.git