簡介
前段時間看到網上有幾篇關於silverlight下雪動畫的文章,看過Demo之后,覺得非常有趣;於是腦海里閃現出一些想法,學習了下,並將其擴展成了以下幾個有趣的web小應用.關於Silverlight下雪動畫的實現方法有很多,這里有篇文章介紹的非常詳細,值得一看: Falling Snow in Silverlight
應用展示
這里有3個擴展的web應用 Merry Christmas, 古風歌曲頁面 以及 情人節快樂!
主要用到了物體飄落的動畫,加之背景圖片音效,以及一些操作功能,使得一個簡單的頁面看起來變得更生動了些.
Merry Christmas(無音樂版) XAP發布包(帶音樂版)
古風歌曲頁面(無音樂版) XAP發布包(帶音樂版)
情人節快樂! (無音樂版) XAP發布包(帶音樂版)
如有需要, 各位男生可以模仿着做個, 送給心怡的她哦 :)
好了,展示就到這里結束,開始我們今天的主題,實現聖誕下雪擴展應用之Merry Christmas!
Merry Christmas 實現
1. 創建Silverlight導航應用程序
首先,我們需要新建一個Silverlight導航應用程序,這里用到了Silverlight導航框架,主要因為它為我們定義好了頁面自適應瀏覽器大小的框架以及頁面頂端的導航控制按鈕. 所以我們稍作修改就可以用了,非常方便.
Silverlight 導航應用程序主頁面
2. 添加應用程序背景
我們在MainPage.xaml頁面添加一張聖誕快樂的背景圖片
<!--背景圖片 Begin--> <Grid.Background> <ImageBrush ImageSource="Images/background_1600_900.jpg" Stretch="Fill" /> </Grid.Background> <!--背景圖片 End-->
運行效果如下, 效果不錯吧 :)
3.下雪效果的實現
首先,我們需要在MainPage.xaml頁面畫出一些靜態的雪花Ellipse.
添加一個用於裝載雪花Ellipse的Canvas;
<Canvas x:Name="CanvasLayOut" Width="1600" Height="900" > </Canvas>
然后,新建個UserControl, 名為SnowEllipse.xaml, 主要用於在Canvas內部動態添加多個Ellipse雪花,並讓其運動.
<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#代碼里實現了 設置雪花屬性 以及 使其運動起來的方法.
/// <summary> /// 設置雪花屬性 /// </summary> /// <param name="snowAreaWidth">雪花可移動區域的寬度</param> /// <param name="snowAreaHeight">雪花可移動區域的高度</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); //設置每個雪花的初始位置 Canvas.SetLeft(this, randomNumber.Next(snowAreaWidth)); Canvas.SetTop(this, randomNumber.Next(snowAreaHeight)); //獲取初始的移動縱坐標 yMovedPosition = Canvas.GetTop(this); //注冊雪花移動方法 循環觸發 CompositionTarget.Rendering += (s, e) => { MoveSnow(); }; }
/// <summary> /// 讓頁面上的雪花動起來 /// </summary> public void MoveSnow() { //移動過程中的位置變化 xMovedPosition += horizontalSpeed; yMovedPosition += verticalSpeed; //設置移動狀態下的雪花坐標 Canvas.SetTop(this, yMovedPosition); Canvas.SetLeft(this, Canvas.GetLeft(this) + radius * Math.Cos(xMovedPosition)); //如果雪花掉落出底部區域 則將其移回頂部 if (Canvas.GetTop(this) > SnowArea.Y) { Canvas.SetTop(this, -30); yMovedPosition = Canvas.GetTop(this); } //如果水平方向超出邊界 則隨機移動到可見區域的某個位置 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里寫點代碼.
DrawStaticSnow()方法主要用於在web頁面畫出靜態雪花,而計時器timer則用於讓靜態的雪花在頁面上飄起來.
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> /// 在頁面上畫出靜態雪花 /// </summary> /// <param name="count">雪花的個數</param> /// <param name="snowAreaWidth">雪花可移動區域的寬度</param> /// <param name="snowAreaHeight">雪花可移動區域的高度</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); } }
於是,雪花漫天飛舞的場景便做成了:) 我們運行下,看看效果.
4. 控制下雪以及增加操作提示功能
為了增加一些我們想要的功能,於是把MainPage.xaml頁面頂部導航欄內容稍作修改.
右側的兩個按鈕改為一個開關下雪和一個操作提示按鈕
<HyperlinkButton x:Name="btnFallingSnowOrNot" Style="{StaticResource LinkStyle}" Content="雪停〉_〈" /> <Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/> <HyperlinkButton x:Name="btnToolTips" Style="{StaticResource LinkStyle}" Content="操作提示" />
針對操作提示按鈕,我們還需要寫個Popup控件,用於在鼠標移上去的時候彈出操作提示框,移出的時候則讓提示框隱藏起來.
<!--操作提示彈出窗口 Begin--> <Popup Name="ppTooltips" HorizontalAlignment="Right" Margin="0 40 140 5" IsOpen="False"> <Border Width="140" Height="165" > <StackPanel Orientation="Vertical"> <TextBlock Text=" 鼠標右鍵有菜單哦" 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-->
接着,我們需要在后端實現這兩個功能:
首先,在MainPage.xaml.cs的構造函數內部加入相應的鼠標事件
//給雪停 和 操作提示 兩個按鈕注冊鼠標事件
btnFallingSnowOrNot.Click += (s, e) => { btnFallingSnowOrNot_Click(s, e); };
btnToolTips.MouseEnter += (s, e) => { btnToolTips_MouseEnter(s, e); };
btnToolTips.MouseLeave += (s, e) => { btnToolTips_MouseLevae(s, e); };
接着實現這些事件, 實現控制下雪事件:
/// <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(); } }
實現操作提示窗體彈出和隱藏事件
/// <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; }
運行下看看
默認為下雪中
點擊雪停,則雪停.
鼠標移到操作提示按鈕上,彈出操作提示.
移開鼠標,操作提示消失.
5. 鼠標右鍵菜單
好了,最后我們需要實現的是一個鼠標右鍵菜單.
實現前,我們需要先給頁面添加一首背景音樂,讓頁面看起來更動感;在MainPage.xaml.cs構造函數內部加入如下代碼.
//添加背景音樂 backgroundMusic.Source = new Uri("/We Wish You A Merry Christmas.mp3", UriKind.RelativeOrAbsolute); backgroundMusic.AutoPlay = true; LayoutRoot.Children.Add(backgroundMusic);
這樣當我們運行的時候 就能聽到美妙動聽的背景音樂了 :)
接着是制作鼠標右鍵菜單:
這里,我們需要先添加一個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代碼,右鍵菜單包含了刷新頁面,開關背景音樂,全屏觀看以及關閉頁面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="關閉音樂" ToolTipService.ToolTip="關閉背景音樂" 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="關閉" ToolTipService.ToolTip="關閉當前頁面" 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-->
之后,在后端相應的菜單按鈕事件下,實現這些方法.
這里需要增加一個Menu類,里面包含了全屏,關閉當前頁面,刷新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("確認關閉當前頁面?(僅在IE下有效)", "退出提示", MessageBoxButton.OKCancel) == MessageBoxResult.OK) { System.Windows.Browser.HtmlPage.Window.Invoke("close"); } } public static void Refresh(Frame frame) { frame.Refresh(); } }
最后是實現我們的右鍵菜單的單擊事件了
/// <summary> /// 鼠標右鍵菜單 /// </summary> private void MenuItem_Click(object sender, RoutedEventArgs e) { MenuItem menuItem = sender as MenuItem; switch (menuItem.Header.ToString()) { case "刷新": timer.Stop(); CanvasLayOut.Children.Clear(); DrawStaticSnow(200, 1600, 900); //重新繪制雪花顆粒 timer.Start(); backgroundMusic.Stop(); backgroundMusic.Play(); break; case "關閉音樂": 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 = "關閉音樂"; ToolTipService.SetToolTip(menuItem, "關閉背景音樂"); 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 "關閉": Menu.Exit(); break; default: break; } }
運行看下
到這里整個下雪的擴展小應用Merry Christmas便完成了 :) Merry Christmas源代碼下載