前段時間看到網(wǎng)上有幾篇關(guān)于silverlight下雪動畫的文章,看過Demo之后,覺得非常有趣;于是腦海里閃現(xiàn)出一些想法,學(xué)習(xí)了下,并將其擴(kuò)展成了以下幾個有趣的web小應(yīng)用.關(guān)于Silverlight下雪動畫的實(shí)現(xiàn)方法有很多,這里有篇文章介紹的非常詳細(xì),值得一看: Falling Snow in Silverlight
這里有3個擴(kuò)展的web應(yīng)用 Merry Christmas, 古風(fēng)歌曲頁面 以及 情人節(jié)快樂!
主要用到了物體飄落的動畫,加之背景圖片音效,以及一些操作功能,使得一個簡單的頁面看起來變得更生動了些.
Merry Christmas 在線效果展示 如果在線看不了可以下載XAP發(fā)布包到本地看
古風(fēng)歌曲頁面 在線效果展示 XAP發(fā)布包
情人節(jié)快樂! 在線效果展示 XAP發(fā)布包
如有需要, 各位男生可以模仿著做個, 送給心怡的她哦 :)
好了,展示就到這里結(jié)束,開始我們今天的主題,實(shí)現(xiàn)圣誕下雪擴(kuò)展應(yīng)用之Merry Christmas!
1. 創(chuàng)建Silverlight導(dǎo)航應(yīng)用程序
首先,我們需要新建一個Silverlight導(dǎo)航應(yīng)用程序,這里用到了Silverlight導(dǎo)航框架,主要因?yàn)樗鼮槲覀兌x好了頁面自適應(yīng)瀏覽器大小的框架以及頁面頂端的導(dǎo)航控制按鈕. 所以我們稍作修改就可以用了,非常方便.
Silverlight 導(dǎo)航應(yīng)用程序主頁面
2. 添加應(yīng)用程序背景
我們在MainPage.xaml頁面添加一張圣誕快樂的背景圖片
<!--背景圖片 Begin--><Grid.Background> <ImageBrush ImageSource="Images/background_1600_900.jpg" Stretch="Fill" /></Grid.Background><!--背景圖片 End-->
運(yùn)行效果如下, 效果不錯吧 :)
3.下雪效果的實(shí)現(xiàn)
首先,我們需要在MainPage.xaml頁面畫出一些靜態(tài)的雪花Ellipse.
添加一個用于裝載雪花Ellipse的Canvas;
<Canvas x:Name="CanvasLayOut" Width="1600" Height="900" > </Canvas>
然后,新建個UserControl, 名為SnowEllipse.xaml, 主要用于在Canvas內(nèi)部動態(tài)添加多個Ellipse雪花,并讓其運(yùn)動.
<UserControl x:Class="SL_MerryChristmas.SnowEllipse" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Width="20" Height="20" > <Grid x:Name="LayoutRoot" > <Ellipse Fill="#FFFFFF" /> </Grid></UserControl>
之后,在后端C#代碼里實(shí)現(xiàn)了 設(shè)置雪花屬性 以及 使其運(yùn)動起來的方法.
/// <summary>/// 設(shè)置雪花屬性 /// </summary>/// <param name="snowAreaWidth">雪花可移動區(qū)域的寬度</param>/// <param name="snowAreaHeight">雪花可移動區(qū)域的高度</param>public void SetSnowEllipse(int snowAreaWidth, int snowAreaHeight){ scale = randomNumber.Next(1, 15); //定義一個中間值 確保高和寬一樣 radius = randomNumber.Next(2); //雪花移動半徑 //水平和垂直方向的移動速度 horizontalSpeed = randomNumber.NextDouble() / 50; verticalSpeed = randomNumber.NextDouble() * 2; //每個雪花的高和寬 this.Width = scale; this.Height = scale; //透明度 this.Opacity = 0.1 + randomNumber.NextDouble(); SnowArea = new Point(snowAreaWidth, snowAreaHeight); //設(shè)置每個雪花的初始位置 Canvas.SetLeft(this, randomNumber.Next(snowAreaWidth)); Canvas.SetTop(this, randomNumber.Next(snowAreaHeight)); ////獲取初始的移動縱坐標(biāo) yMovedPosition = Canvas.GetTop(this); //綁定雪花移動事件 循環(huán)觸發(fā) CompositionTarget.Rendering += (s, e) => { MoveSnow(); };}
/// <summary>/// 讓頁面上的雪花動起來/// </summary>public void MoveSnow(){ //移動過程中的位置變化 xMovedPosition += horizontalSpeed; yMovedPosition += verticalSpeed; //設(shè)置移動狀態(tài)下的雪花坐標(biāo) Canvas.SetTop(this, yMovedPosition); Canvas.SetLeft(this, Canvas.GetLeft(this) + radius * Math.Cos(xMovedPosition)); //如果雪花掉落出底部區(qū)域 則將其移回頂部 if (Canvas.GetTop(this) > SnowArea.Y) { Canvas.SetTop(this, -30); yMovedPosition = Canvas.GetTop(this); } //如果水平方向超出邊界 則隨機(jī)移動到可見區(qū)域的某個位置 if (Canvas.GetLeft(this) > SnowArea.X || Canvas.GetLeft(this) < 0) { Canvas.SetLeft(this, randomNumber.Next((int)SnowArea.X)); xMovedPosition = Canvas.GetLeft(this); }}
為了能讓程序跑起來,我們需要在MainPage.xaml.cs里寫點(diǎn)代碼.
DrawStaticSnow()方法主要用于在web頁面畫出靜態(tài)雪花,而計(jì)時器timer則用于讓靜態(tài)的雪花在頁面上飄起來.
SnowEllipse snowEllipse = new SnowEllipse();private DispatcherTimer timer = new DispatcherTimer();public MainPage(){ InitializeComponent(); //畫雪花 DrawStaticSnow(200, 1600, 900); //讓雪花動起來 snowEllipse = new SnowEllipse(); timer.Interval = TimeSpan.FromMilliseconds(5); timer.Tick += (s, e) => { snowEllipse.MoveSnow(); }; timer.Start();}
/// <summary>/// 在頁面上畫出靜態(tài)雪花/// </summary>/// <param name="count">雪花的個數(shù)</param>/// <param name="snowAreaWidth">雪花可移動區(qū)域的寬度</param>/// <param name="snowAreaHeight">雪花可移動區(qū)域的高度</param>public void DrawStaticSnow(int count, int snowAreaWidth, int snowAreaHeight){ for (int i = 0; i < count; ++i) { snowEllipse = new SnowEllipse(); snowEllipse.SetSnowEllipse(snowAreaWidth, snowAreaHeight); CanvasLayOut.Children.Add(snowEllipse); }}
于是,雪花漫天飛舞的場景便做成了:) 我們運(yùn)行下,看看效果.
4. 控制下雪以及增加操作提示功能
為了增加一些我們想要的功能,于是把MainPage.xaml頁面頂部導(dǎo)航欄內(nèi)容稍作修改.
右側(cè)的兩個按鈕改為一個開關(guān)下雪和一個操作提示按鈕
<HyperlinkButton x:Name="btnFallingSnowOrNot" Style="{StaticResource LinkStyle}" Content="雪?!礯〈" /><Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/><HyperlinkButton x:Name="btnToolTips" Style="{StaticResource LinkStyle}" Content="操作提示" />
針對操作提示按鈕,我們還需要寫個Popup控件,用于在鼠標(biāo)移上去的時候彈出操作提示框,移出的時候則讓提示框隱藏起來.
<!--操作提示彈出窗口 Begin--> <Popup Name="ppTooltips" HorizontalAlignment="Right" Margin="0 40 140 5" IsOpen="False"> <Border Width="140" Height="165" > <StackPanel Orientation="Vertical"> <TextBlock Text=" 鼠標(biāo)右鍵有菜單哦" Width="140" FontSize="14" Height="20" Margin="0 3 0 0" Foreground="White" FontWeight="Bold"></TextBlock> <Image Source="Images/Menu/Menu.png" Width="114" Height="130"></Image> </StackPanel> </Border> </Popup> <!--操作提示彈出窗口 End-->
接著,我們需要在后端實(shí)現(xiàn)這兩個功能:
首先,在MainPage.xaml.cs的構(gòu)造函數(shù)內(nèi)部加入相應(yīng)的鼠標(biāo)事件
//給雪停 和 操作提示 兩個按鈕加載鼠標(biāo)事件btnFallingSnowOrNot.Click += (s, e) => { btnFallingSnowOrNot_Click(s, e); };btnToolTips.MouseEnter += (s, e) => { btnToolTips_MouseEnter(s, e); };btnToolTips.MouseLeave += (s, e) => { btnToolTips_MouseLevae(s, e); };
接著實(shí)現(xiàn)這些事件, 實(shí)現(xiàn)控制下雪事件:
/// <summary>/// 控制下雪單擊事件/// </summary>private void btnFallingSnowOrNot_Click(object sender, RoutedEventArgs e){ if (timer.IsEnabled) { btnFallingSnowOrNot.Content = "雪下∩_∩"; timer.Stop(); CanvasLayOut.Children.Clear(); //移除所有的雪花顆粒 } else if (!timer.IsEnabled) { btnFallingSnowOrNot.Content = "雪?!礯〈"; DrawStaticSnow(200, 1600, 900); //重新繪制雪花顆粒 timer.Start(); }}
實(shí)現(xiàn)操作提示窗體彈出和隱藏事件
/// <summary>/// 提示窗體的彈出和隱藏事件/// </summary>private void btnToolTips_MouseEnter(object sender, MouseEventArgs e){ if (!ppTooltips.IsOpen) ppTooltips.IsOpen = true;}private void btnToolTips_MouseLevae(object sender, MouseEventArgs e){ if (ppTooltips.IsOpen) ppTooltips.IsOpen = false;}
運(yùn)行下看看
默認(rèn)為下雪中
點(diǎn)擊雪停,則雪停.
鼠標(biāo)移到操作提示按鈕上,彈出操作提示.
移開鼠標(biāo),操作提示消失.
5. 鼠標(biāo)右鍵菜單
好了,最后我們需要實(shí)現(xiàn)的是一個鼠標(biāo)右鍵菜單.
實(shí)現(xiàn)前,我們需要先給頁面添加一首背景音樂,讓頁面看起來更動感;在MainPage.xaml.cs構(gòu)造函數(shù)內(nèi)部加入如下代碼.
//添加背景音樂backgroundMusic.Source = new Uri("/We Wish You A Merry Christmas.mp3", UriKind.RelativeOrAbsolute);backgroundMusic.AutoPlay = true;LayoutRoot.Children.Add(backgroundMusic);
這樣當(dāng)我們運(yùn)行的時候 就能聽到美妙動聽的背景音樂了 :)
接著是制作鼠標(biāo)右鍵菜單:
這里,我們需要先添加一個System.Windows.Controls.Input.Toolkit dll的引用.
如果添加引用里沒有的話可以去這里下載 http://silverlight.codeplex.com/releases/view/43528/
然后在MainPage.xaml里引用它
xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
并添加右鍵菜單的XAML代碼,右鍵菜單包含了刷新頁面,開關(guān)背景音樂,全屏觀看以及關(guān)閉頁面4個方法.
<!--右鍵菜單 Begin--> <my:ContextMenuService.ContextMenu> <my:ContextMenu FontSize="14" FontStyle="Normal" Foreground="#0087CB" BorderBrush="#0087CB" BorderThickness="2" > <my:MenuItem Header="刷新" ToolTipService.ToolTip="刷新頁面" Click="MenuItem_Click"> <my:MenuItem.Icon> <Image Source="Images/Menu/Refresh_blue.png"/> </my:MenuItem.Icon> </my:MenuItem> <my:Separator/> <my:MenuItem x:Name="itemCloseMusic" Header="關(guān)閉音樂" ToolTipService.ToolTip="關(guān)閉背景音樂" Click="MenuItem_Click"> <my:MenuItem.Icon> <Image x:Name="imgPlay" Source="Images/Menu/Player Stop_blue.png" Width="16" Height="16" /> </my:MenuItem.Icon> </my:MenuItem> <my:Separator/> <my:MenuItem x:Name="itemFullScreen" Header="全屏模式" ToolTipService.ToolTip="啟動全屏模式" Click="MenuItem_Click"> <my:MenuItem.Icon> <Image Source="Images/Menu/Full Size_blue.png" Width="16" Height="16" /> </my:MenuItem.Icon> </my:MenuItem> <my:Separator/> <my:MenuItem Header="關(guān)閉" ToolTipService.ToolTip="關(guān)閉當(dāng)前頁面" Click="MenuItem_Click"> <my:MenuItem.Icon> <Image Source="Images/Menu/Exit_blue.png" Width="16" Height="16" /> </my:MenuItem.Icon> </my:MenuItem> </my:ContextMenu> </my:ContextMenuService.ContextMenu> <!--右鍵菜單 End-->
之后,在后端相應(yīng)的菜單按鈕事件下,實(shí)現(xiàn)這些方法.
這里需要增加一個Menu類,里面包含了全屏,關(guān)閉當(dāng)前頁面,刷新3個方法.
public class Menu{ public static string FullScreen(string screenState) { if (screenState == "全屏模式") screenState = "退出全屏"; else screenState = "全屏模式"; if (!Application.Current.Host.Content.IsFullScreen) Application.Current.Host.Content.IsFullScreen = true; else Application.Current.Host.Content.IsFullScreen = false; return screenState; } public static void Exit() { if (MessageBox.Show("確認(rèn)關(guān)閉當(dāng)前頁面?(僅在IE下有效)", "退出提示", MessageBoxButton.OKCancel) == MessageBoxResult.OK) { System.Windows.Browser.HtmlPage.Window.Invoke("close"); } } public static void Refresh(Frame frame) { frame.Refresh(); }}
最后是實(shí)現(xiàn)我們的右鍵菜單的單擊事件了
/// <summary>/// 鼠標(biāo)右鍵菜單/// </summary>private void MenuItem_Click(object sender, RoutedEventArgs e){ MenuItem menuItem = sender as MenuItem; switch (menuItem.Header.ToString()) { case "刷新": Menu.Refresh(this.ContentFrame); backgroundMusic.Stop(); backgroundMusic.Play(); break; case "關(guān)閉音樂": backgroundMusic.Stop(); menuItem.Header = "開啟音樂"; ToolTipService.SetToolTip(menuItem, "開啟背景音樂"); Uri uriPlay = new Uri("Images/Menu/Player Play_blue.png", UriKind.RelativeOrAbsolute); BitmapImage bitImg = new BitmapImage(uriPlay); imgPlay.Source = bitImg; break; case "開啟音樂": backgroundMusic.Play(); menuItem.Header = "關(guān)閉音樂"; ToolTipService.SetToolTip(menuItem, "關(guān)閉背景音樂"); Uri uriStop = new Uri("Images/Menu/Player Stop_blue.png", UriKind.RelativeOrAbsolute); BitmapImage bitImg2 = new BitmapImage(uriStop); imgPlay.Source = bitImg2; break; case "全屏模式": menuItem.Header = Menu.FullScreen(menuItem.Header.ToString()); ToolTipService.SetToolTip(menuItem, "退出全屏模式"); break; case "退出全屏": menuItem.Header = Menu.FullScreen(menuItem.Header.ToString()); ToolTipService.SetToolTip(menuItem, "啟動全屏模式"); break; case "關(guān)閉": Menu.Exit(); break; default: break; }}
運(yùn)行看下
到這里整個下雪的擴(kuò)展小應(yīng)用Merry Christmas便完成了 :) Merry Christmas源代碼下載