Loading

WPF实现聚光灯效果

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

Github https://github.com/WPFDevelopersOrg

码云 https://gitee.com/WPFDevelopersOrg

posted @ 2021-10-11 09:52  驚鏵  阅读(1140)  评论(9编辑  收藏  举报