草庐IT

来瞧瞧,WPF 炫酷走马灯!

驚鏵 2023-03-28 原文

来瞧瞧,WPF 炫酷走马灯!

控件名:SpotLight

作者:WPFDevelopersOrg

原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用大于等于.NET40

  • Visual Studio 2022;

  • 项目使用 MIT 开源许可协议;

  • Canvas做容器方便针对文本TextBlock做裁剪Clip动画操作;

  • Canvas内部创建两个TextBlock

  • 第一个做为背景字体设置字体颜色为浅灰Foreground="#323232",也可以通过依赖属性设置DefaultForeground

  • 第二个字体设置会彩虹色当聚光灯走到某个区域后并显示;

  • Duration可设置动画的从左到右的时长,默认3秒;

  • 根据字体的实际宽度ActualWidth做动画展示从左到右并循环Forever播放;

1)SpotLight.cs 代码如下;

using System;
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";

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(SpotLight),
                new PropertyMetadata("WPFDevelopers"));

        public static readonly DependencyProperty DefaultForegroundProperty =
            DependencyProperty.Register("DefaultForeground", typeof(Brush), typeof(SpotLight),
                new PropertyMetadata(new SolidColorBrush((Color)ColorConverter.ConvertFromString("#323232"))));


        public static readonly DependencyProperty DurationProperty =
            DependencyProperty.Register("Duration", typeof(TimeSpan), typeof(SpotLight),
                new PropertyMetadata(TimeSpan.FromSeconds(3)));


        private EllipseGeometry _ellipseGeometry;
        private TextBlock _textBlockBottom, _textBlockTop;

        static SpotLight()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(SpotLight),
                new FrameworkPropertyMetadata(typeof(SpotLight)));
        }

       
        public TimeSpan Duration
        {
            get => (TimeSpan)GetValue(DurationProperty);
            set => SetValue(DurationProperty, value);
        }
        public Brush DefaultForeground
        {
            get => (Brush)GetValue(DefaultForegroundProperty);
            set => SetValue(DefaultForegroundProperty, value);
        }

        public string Text
        {
            get => (string)GetValue(TextProperty);
            set => SetValue(TextProperty, value);
        }
        
        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
            {
                From = 0,
                To = _textBlockTop.ActualWidth,
                Duration = Duration
            };

            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.Begin();
        }
    }
}

2)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>
    <LinearGradientBrush x:Key="RainbowBrush" 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>
    <Style TargetType="{x:Type controls:SpotLight}" BasedOn="{StaticResource ControlBasicStyle}">
        <Setter Property="Background" Value="#222222"/>
        <Setter Property="FontSize" Value="60"/>
        <Setter Property="FontFamily" Value="Arial Black"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Foreground" Value="{StaticResource RainbowBrush}"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:SpotLight}">
                    <Grid x:Name="PART_Canvas" Background="{TemplateBinding Background}">
                        <TextBlock x:Name="PART_TextBlockBottom" Text="{TemplateBinding Text}"
                                   FontSize="{TemplateBinding FontSize}" 
                                   FontFamily="{TemplateBinding FontFamily}"
                                   FontWeight="{TemplateBinding FontWeight}" 
                                   Foreground="{TemplateBinding DefaultForeground}"/>
                        <TextBlock x:Name="PART_TextBlockTop" Text="{TemplateBinding Text}"
                                   FontSize="{TemplateBinding FontSize}"
                                   FontFamily="{TemplateBinding FontFamily}"
                                   FontWeight="{TemplateBinding FontWeight}"
                                   Foreground="{TemplateBinding Foreground}">
                            <TextBlock.Clip>
                                <EllipseGeometry x:Name="PART_EllipseGeometry">
                                    <EllipseGeometry.Transform>
                                        <TranslateTransform/>
                                    </EllipseGeometry.Transform>
                                </EllipseGeometry>
                            </TextBlock.Clip>
                        </TextBlock>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

3)SpotLightExample.xaml代码如下如何使用

<UniformGrid Rows="2" Background="#222222">
        <wpfdev:SpotLight FontSize="50" Text="YanJinHua" 
                          DefaultForeground="Crimson" 
                          Foreground="Fuchsia" 
                          Duration="00:00:05" />
        <wpfdev:SpotLight/>
</UniformGrid>

SpotLight.cs|Github
SpotLight.cs|码云
SpotLight.xaml|Github
SpotLight.xaml|码云

有关来瞧瞧,WPF 炫酷走马灯!的更多相关文章

  1. 可以加载mpusbapi.dll c#.net WPF项目 - 2

    我需要构建一个GUI,以通过WindowsPC通过批量USB通信到PIC微控制器。我正在尝试使用mpusbapi.dll正如我在Internet上看到的不同教程时,我无法成功地引用项目中的DLL。vs2015向我展示了这个错误:无法添加“mpusbapi.dll”。确保该文件可访问,并且是valis组件或com组件。我进行了研究,我发现问题是未管理的DLL,所以我试图通过Dllimport参考。但是目前,这也没有起作用。我在下面分享我的代码,期望某人可以帮助我或给我一些更好的方法来实现我的目标。usingSystem.Runtime.InteropServices;namespaceGUI_R

  2. c# - 我可以在不使用浏览器对象的情况下直接在 WPF 中调用 javascript 吗? - 2

    我希望能够直接在我的WPF应用程序上创建一个使用开放层的应用程序。我发现我可以创建浏览器对象并调用JavaScript,但我不需要完整的浏览器。是否有一些脚本对象我可以使用并一起绕过浏览器对象? 最佳答案 您不需要Web浏览器或WebBrowser控件即可在NETFramework中使用JavaScript。NETFramework有一个内置的JavaScript实现,它实现了JavaScript/ECMAScript的超集,如here所述。和here.要使用NETFramework的内置JavaScript实现:添加对Micros

  3. c# - 获取 WPF 网页浏览器 HTML - 2

    我正在使用WpfWebBrowser访问某个页面。我需要获取它的HTML内容——我不能使用Webclient或WebReques等,因为我需要在该页面上执行JS。我还尝试了Awesomium和WfWebBrowser(都错了)。dynamicdoc=browser.Document;vartext=doc.InnerHtml//orsomethinglikethis上面的代码对我不起作用,它显示空引用。谁能告诉我如何获取它?我已经搜索了数周,但没有发现任何真正有效的东西:/。请像您能想象到的最大笨蛋一样回答:D。有时我会遇到有人发给我一段代码,但我不知道如何使用它...我的意思是请让你

  4. javascript - WPF - 调用 javascript 函数时出错 - 未知名称。 (来自 HRESULT : 0x80020006 (DISP_E_UNKNOWNNAME)) 的异常 - 2

    我在我的wpf应用程序中使用“WebBroswer”来呈现Googlemap。因此,我使用C#代码中的一些参数调用Pan(x,y)JavaScript方法。但我收到以下错误。Unknownname.(ExceptionfromHRESULT:0x80020006(DISP_E_UNKNOWNNAME))我的Window2.xaml文件:Button我的Window2.xaml.cs文件:namespaceTest{//////InteractionlogicforWindow2.xaml///publicpartialclassWindow2:Window{publicWindow2(

  5. WPF工控组态软件之管道和冷却风扇开发 - 2

    WPF以其丰富灵活的控件样式设计,相较于WinForm而言,一直是工控组态软件的宠儿,本文以两个简单的小例子,简述如何通过WPF设计出表示水流的管道,和转动的冷却风扇。仅供学习分享使用,如有不足之处,还请指正。设计知识点关于本示例中,涉及的知识点,如下所示:自定义用户控件,用户可以根据业务需要自定义控件,将普通的控件进行组合,封装,以满足特定的功能,并达到复用的目的。WPF形状,动画,可以通过选择,移动,变形等相关功能,改变控件的呈现形状。依赖属性,WPF可以通过依赖属性进行数据的绑定,实现UI与业务逻辑的解耦。示例截图 本示例主要实现了管道,和冷却扇,然后通过不同的旋转,移动并加以组合,如下

  6. 不需要任何插件,纯 CSS 就能打造炫酷文字特效 - 2

    前言现如今网页越来越趋近于动画,相信大家平时浏览网页或多或少都能看到一些动画效果,今天我们来做一些文字上面的动画效果,下面一起看看吧。1.文字抖动实现效果实现思路其实主要就是通过animation添加动画属性,利用keyframes来描述动画的开始、过程和结束的状态,核心就是animation+transform:rotate,话不多说,下面直接看代码。完整源码template>divclass="parentBox">divclass="contantBox">文字抖动/div>/div>/template>stylelang="less"scoped>.parentBox{height:1

  7. WPF HALCON HSmartWindowControlWPF 鼠标绘制ROI - 2

    0.需求在HSmartWindowsControlWPF上用鼠标绘制ROI,且显示绘制时的鼠标交互过程,最终效果如下:1.基本思路在HSmartWindowControl上布置一层透明的Canvas,用于实时显示鼠标绘制ROI的过程鼠标移动时,在Canvas上用鼠标实时绘制Rectangle等ROI形状,鼠标在Canvas坐标系中的Position信息(x,y)坐标转换到HALCON图像坐标系,变换为Row、Column等信息根据Row、Column信息调用HDrawingObject.CreateDrawingObject()方法生成Halcon原生ROI鼠标左键释放时,隐藏Canvas,将

  8. c# - WPF ObservableCollection 两种方式绑定(bind) XML 文件 - 2

    我想将一个ObservableCollection绑定(bind)到一个XML文件。在的多次回复之前YoushouldbindyourDataGrid,ComboBox,etc..directlytotheXMLfile请注意ObservableCollection已经存在并且已经绑定(bind)到DataGrid、ComboBox等...重写所有代码对我来说听起来一点也不有趣。尽管我所做的关于将XML文件绑定(bind)到ObservableCollection的每个搜索都会直接返回XML文件的绑定(bind)对象。是的,我知道我可以自己手动添加、更新和删除,但我希望不必这样做。

  9. c# - 在 WPF 中运行时 xml 文档更改时如何刷新 xmlDataProvider? - 2

    我正在尝试在visualstudiowpf中制作图像查看器/相册创建器。每个相册的图像路径都存储在一个xml文档中,我绑定(bind)到该文档以在列表框中显示每个相册中的图像。问题是当我在运行时添加图像或相册并将其写入xml文档时。我似乎无法对xml文档更新进行绑定(bind),因此它们也会显示新图像和相册。在XmlDataProvider上调用Refresh()不会改变任何内容。我不想重做XmlDataProvider的绑定(bind),只是让它再次从同一源读取。XAML:............代码隐藏:privatevoidnewImagePathButton_Click(obj

  10. wpf - 强制 XML 具有结束标记? - 2

    我有一个创建XDocument的代码,我在其中使用System.Xml.Linq类添加了XElements。唯一的问题是,如果xml节点没有值,它会返回一个已经关闭的标签。即但我有点想创建一个同时显示开始标记和结束标记的XML。即即使它没有值(value)。有什么方法可以使它看起来像这样吗?P.S.:我将这段代码保存在数据库中,在一个接受数据类型xml的表列下,因此添加一个字符串。在数据库上关闭Empty,所以FML。有什么想法吗? 最佳答案 尝试分配InnerTextXmlNode的"".此操作显然会使它扩展为形式。

随机推荐