html特效 wpf,WPF实现简单的跑马灯效果

最近项目上要用到跑马灯的效果,和网上不太相同的是,网上大部分都是连续的,而我们要求的是不连续的。

也就是是,界面上就展示4项(展示项数可变),如果有7项要展示的话,则不断的在4个空格里左跳,当然,衔接上效果不是很好看。

然后,需要支持点击以后进行移除掉不再显示的内容。

效果如下:

f5404acf88bee67f5a56aca184db8163.gif

思路大致如下:

1、最外层用一个ViewBox,为了可以填充调用此控件的地方,这样可以方便自动拉伸

2、定义三个变量,一个是Count值,是为了设定要展示的UserControl的个数的,例如默认是4个,如效果图,当然,设置成5的话,就是5个了;一个List是为了放入展示控件的列表,一个List是用来放所有要用于跑马灯里的控件的。

3、设置一个Canvas,放入到最外层的Viewbox中,用于跑马灯时候用(这也是常用的跑马灯控件Canvas)

//给Canvas设置一些属性

canvas_board.VerticalAlignment = VerticalAlignment.Stretch;

canvas_board.HorizontalAlignment = HorizontalAlignment.Stretch;

canvas_board.Width = this.viewbox_main.ActualWidth;

canvas_board.Height = this.viewbox_main.ActualHeight;

canvas_board.ClipToBounds = true;

//用viewbox可以支持拉伸

this.viewbox_main.Child = canvas_board;

4、将要循环的Grid放入到Canvas里,这里的Grid的个数,要比展示的个数大一个,也就是Count+1个值,因为滚动的时候,其实是在最外面有一个的,这样保证了循环的走动。至于两个控件之间的Margin这个就是要设置Grid的了,到时候控件是直接扔进Grid里的

//循环将Grid加入到要展示的列表里

for (int i = 0; i < Uc_Count + 1; i++)

{

Grid grid = new Grid();

grid.Width = canvas_board.Width / Uc_Count - 10;

grid.Height = canvas_board.Height - 10;

grid.Margin = new Thickness(5);

this.canvas_board.Children.Add(grid);

grid.SetValue(Canvas.TopProperty, 0.0);

grid.SetValue(Canvas.LeftProperty, i * (grid.Width + 10));

UcListForShow.Add(grid);

}

5、给每个Grid增加一个动画效果,就是向左移动的效果

for (int i = 0; i < UcListForShow.Count; i++)

{

//设置滚动时候的效果

DoubleAnimationUsingKeyFrames daukf_uc = new DoubleAnimationUsingKeyFrames();

LinearDoubleKeyFrame k1_uc = new LinearDoubleKeyFrame(i * (UcListForShow[i].Width + 10), KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2)));

LinearDoubleKeyFrame k2_uc = new LinearDoubleKeyFrame((i - 1) * (UcListForShow[i].Width + 10), KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.5)));

daukf_uc.KeyFrames.Add(k1_uc);

daukf_uc.KeyFrames.Add(k2_uc);

storyboard_imgs.Children.Add(daukf_uc);

Storyboard.SetTarget(daukf_uc, UcListForShow[i]);

Storyboard.SetTargetProperty(daukf_uc, new PropertyPath("(Canvas.Left)"));

}

6、滚动的时候,要计算UserControl到底是添加到了哪个Grid里面,也就是哪个控件作为了第一位。

我们设置一个索引值scroll_index,默认的时候,scroll_index=0,这是初始的状态,当滚动起来以后,scroll_index = scroll_index + 1 - Uc_Count;

然后,判断,循环的时候,是否是展示列表的末尾了,如果是的话,则要填充的控件是scroll_index %UcListSum.Count(滚动索引,对总数直接取余数),如果不是的话则是scroll_index++ % UcListSum.Count(滚动索引++,对总数直接取余数)

scroll_index = scroll_index + 1 - Uc_Count;

for (int i = 0; i < UcListForShow.Count; i++)

{

UcListForShow[i].SetValue(Canvas.LeftProperty, i * (UcListForShow[i].Width + 10));

UserControl uc;

if (i == UcListForShow.Count - 1)

{

uc = UcListSum[scroll_index % UcListSum.Count];

}

else

{

uc = UcListSum[scroll_index++ % UcListSum.Count];

}

if (uc.Parent != null)

{

(uc.Parent as Grid).Children.Clear();//将Usercontrol从原来的里面移除掉,要不然会抛错,Usercontrol已属于另一个控件

}

UcListForShow[i].Children.Clear();

UcListForShow[i].Children.Add(uc);

//将隐藏按钮加入到Grid里

Button btn = new Button();

btn.Style = (dictionary["hidenStyle"] as Style);//从样式文件里读取到Button的样式

btn.Tag = UcListForShow[i].Children;//给Tag赋值,这样方便查找

btn.Click += Btn_Click;//注册隐藏事件

UcListForShow[i].Children.Add(btn);

}

代码中,需要注意的是(uc.Parent as Grid).Children.Clear(),如果不移除的话,则会提示,已经属于另一个,所以,要从parent里面移除掉。

7、Button的隐藏事件,当Button点击以后,则要进行隐藏,其实也就是将总数里面,减除掉不再显示的那一项

private void Btn_Click(object sender, RoutedEventArgs e)

{

if ((sender as Button).Tag != null)

{

UcListSum.Remove((((sender as Button).Tag as UIElementCollection)[0] as UserControl));

}

if (UcListSum.Count == Uc_Count)//当列表数和要展示的数目相同的时候,就停止掉动画效果

{

storyboard_imgs.Completed -= Storyboard_imgs_Completed;

storyboard_imgs.Stop();

for (int i = 0; i < Uc_Count; i++)

{

UcListForShow[i].Children.Clear();

if (UcListSum[i].Parent != null)

{

(UcListSum[i].Parent as Grid).Children.Clear();

}

UcListForShow[i].Children.Add(UcListSum[i]);

}

return;

}

}

所有代码如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

namespace MarqueeUserControl

{

///

/// MarqueeUC.xaml 的交互逻辑

///

public partial class MarqueeUC : UserControl

{

ResourceDictionary dictionary;

public MarqueeUC()

{

InitializeComponent();

//读取样式文件

dictionary = new ResourceDictionary { Source = new Uri("/MarqueeUserControl;component/MarqueeUserControlDictionary.xaml", UriKind.Relative) };

}

#region 属性

private int _uc_Count = 0;

///

/// 用来展示几个

///

public int Uc_Count

{

get

{

return _uc_Count;

}

set

{

_uc_Count = value;

}

}

private List _ucListForShow = new List();

///

/// 用来展示的控件列表

///

private List UcListForShow

{

get

{

return _ucListForShow;

}

set

{

_ucListForShow = value;

}

}

private List _ucListSum = new List();

///

/// 要添加的控件的列表

///

public List UcListSum

{

get

{

return _ucListSum;

}

set

{

_ucListSum = value;

}

}

#endregion

Canvas canvas_board = new Canvas();

Storyboard storyboard_imgs = new Storyboard();

int scroll_index = 0;//滚动索引

double scroll_width;//滚动宽度

void GridLayout()

{

if (Uc_Count == 0)//如果这个值没有赋值的话,则默认显示四个

{

Uc_Count = 4;

}

//给Canvas设置一些属性

canvas_board.VerticalAlignment = VerticalAlignment.Stretch;

canvas_board.HorizontalAlignment = HorizontalAlignment.Stretch;

canvas_board.Width = this.viewbox_main.ActualWidth;

canvas_board.Height = this.viewbox_main.ActualHeight;

canvas_board.ClipToBounds = true;

//用viewbox可以支持拉伸

this.viewbox_main.Child = canvas_board;

//循环将Grid加入到要展示的列表里

for (int i = 0; i < Uc_Count + 1; i++)

{

Grid grid = new Grid();

grid.Width = canvas_board.Width / Uc_Count - 10;

grid.Height = canvas_board.Height - 10;

grid.Margin = new Thickness(5);

this.canvas_board.Children.Add(grid);

grid.SetValue(Canvas.TopProperty, 0.0);

grid.SetValue(Canvas.LeftProperty, i * (grid.Width + 10));

UcListForShow.Add(grid);

}

}

void StoryLoad()

{

for (int i = 0; i < UcListForShow.Count; i++)

{//设置滚动时候的效果

DoubleAnimationUsingKeyFrames daukf_uc = new DoubleAnimationUsingKeyFrames();

LinearDoubleKeyFrame k1_uc = new LinearDoubleKeyFrame(i * (UcListForShow[i].Width + 10), KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2)));

LinearDoubleKeyFrame k2_uc = new LinearDoubleKeyFrame((i - 1) * (UcListForShow[i].Width + 10), KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.5)));

daukf_uc.KeyFrames.Add(k1_uc);

daukf_uc.KeyFrames.Add(k2_uc);

storyboard_imgs.Children.Add(daukf_uc);

Storyboard.SetTarget(daukf_uc, UcListForShow[i]);

Storyboard.SetTargetProperty(daukf_uc, new PropertyPath("(Canvas.Left)"));

}

storyboard_imgs.FillBehavior = FillBehavior.Stop;

storyboard_imgs.Completed += Storyboard_imgs_Completed;

storyboard_imgs.Begin();

}

private void Storyboard_imgs_Completed(object sender, EventArgs e)

{

scroll_index = scroll_index + 1 - Uc_Count;

for (int i = 0; i < UcListForShow.Count; i++)

{

UcListForShow[i].SetValue(Canvas.LeftProperty, i * (UcListForShow[i].Width + 10));

UserControl uc;

if (i == UcListForShow.Count - 1)

{

uc = UcListSum[scroll_index % UcListSum.Count];

}

else

{

uc = UcListSum[scroll_index++ % UcListSum.Count];

}

if (uc.Parent != null)

{

(uc.Parent as Grid).Children.Clear();//将Usercontrol从原来的里面移除掉,要不然会抛错,Usercontrol已属于另一个控件

}

UcListForShow[i].Children.Clear();

UcListForShow[i].Children.Add(uc);

//将隐藏按钮加入到Grid里

Button btn = new Button();

btn.Style = (dictionary["hidenStyle"] as Style);//从样式文件里读取到Button的样式

btn.Tag = UcListForShow[i].Children;//给Tag赋值,这样方便查找

btn.Click += Btn_Click;//注册隐藏事件

UcListForShow[i].Children.Add(btn);

}

storyboard_imgs.Begin();

}

private void Btn_Click(object sender, RoutedEventArgs e)

{

if ((sender as Button).Tag != null)

{

UcListSum.Remove((((sender as Button).Tag as UIElementCollection)[0] as UserControl));

}

if (UcListSum.Count == Uc_Count)//当列表数和要展示的数目相同的时候,就停止掉动画效果

{

storyboard_imgs.Completed -= Storyboard_imgs_Completed;

storyboard_imgs.Stop();

for (int i = 0; i < Uc_Count; i++)

{

UcListForShow[i].Children.Clear();

if (UcListSum[i].Parent != null)

{

(UcListSum[i].Parent as Grid).Children.Clear();

}

UcListForShow[i].Children.Add(UcListSum[i]);

}

return;

}

}

public void StartMar()

{

GridLayout();

scroll_width = this.canvas_board.Width;

for (int i = 0; i < UcListForShow.Count; i++)

{

UserControl uc;

if (i == UcListForShow.Count - 1)

{

uc = UcListSum[scroll_index % UcListSum.Count];

}

else

{

uc = UcListSum[scroll_index++ % UcListSum.Count];

}

if (uc.Parent != null)

{

(uc.Parent as Grid).Children.Clear();

}

UcListForShow[i].Children.Clear();

UcListForShow[i].Children.Add(uc);

}

StoryLoad();

}

private void grid_main_MouseLeave(object sender, MouseEventArgs e)

{

if (storyboard_imgs.GetCurrentState() == ClockState.Stopped)//如果是停止的状态,则直接返回,不再起作用

{

return;

}

if (storyboard_imgs.GetIsPaused() == true)//如果是暂停状态的话,则开始

{

storyboard_imgs.Begin();

}

}

private void grid_main_MouseMove(object sender, MouseEventArgs e)

{

if (storyboard_imgs.GetIsPaused() == false)

{

storyboard_imgs.Pause();

}

}

}

}

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="clr-namespace:MarqueeUserControl">

没有解决的问题

想给Button增加鼠标悬停的时候,显示,移除的时候隐藏,但是发现不好使,原因是当MouseOver上去的时候,虽然Visibility的值变了,但是只有到下一次的时候,Button的值才被附上,而此时,已经MouseLeave了,请哪位大神指导一下,看看这个显示和隐藏怎么做。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF 中可以使用 Animation 和 VisualBrush 来实现定点跑马灯效果。 首先,创建一个 TextBlock 控件,并将其包含在一个 Canvas 中。将 TextBlock 的内容设置为需要展示的文本。假设 Canvas 的宽度为 300,TextBlock 的宽度为 200。 ```xml <Canvas Width="300"> <TextBlock Text="这是一段需要展示的文本" Width="200" /> </Canvas> ``` 接下来,在 Canvas 中添加一个矩形,用于遮挡 TextBlock 的部分内容。将矩形的宽度设置为 100,高度设置为 TextBlock 的高度。将矩形的 Fill 属性设置为一个 VisualBrush,该 VisualBrush 的视觉元素是 TextBlock,并且其对齐方式设置为左对齐。这样,当矩形向右移动时,TextBlock 的内容也会向左移动,从而实现跑马灯效果。 ```xml <Canvas Width="300"> <TextBlock Text="这是一段需要展示的文本" Width="200" /> <Rectangle Width="100" Height="{Binding ActualHeight, ElementName=TextBlock}"> <Rectangle.Fill> <VisualBrush Visual="{Binding ElementName=TextBlock}" AlignmentX="Left" Viewport="-100,0,200,1" ViewportUnits="Absolute" TileMode="Tile"/> </Rectangle.Fill> </Rectangle> </Canvas> ``` 最后,使用一个 Storyboard 来控制矩形的移动。将矩形的 Canvas.Left 属性绑定到一个 DoubleAnimation 的 To 属性,并设置 Duration 和 RepeatBehavior 属性。这样,矩形会在 Canvas 上水平移动,从而实现跑马灯效果。 ```xml <Canvas Width="300"> <TextBlock Text="这是一段需要展示的文本" Width="200" /> <Rectangle Width="100" Height="{Binding ActualHeight, ElementName=TextBlock}" Canvas.Left="0"> <Rectangle.Fill> <VisualBrush Visual="{Binding ElementName=TextBlock}" AlignmentX="Left" Viewport="-100,0,200,1" ViewportUnits="Absolute" TileMode="Tile"/> </Rectangle.Fill> <Rectangle.Triggers> <EventTrigger RoutedEvent="Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" To="-100" Duration="0:0:5" RepeatBehavior="Forever" /> </Storyboard> </BeginStoryboard> </EventTrigger> </Rectangle.Triggers> </Rectangle> </Canvas> ``` 这样,就实现了一个简单的定点跑马灯效果

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值