前言canvas
看到過其餘平臺遊戲中第三方sdk的一些懸浮的小助手,近來無聊,就作個玩兒,看着比較簡單,作起來仍是花費了很多力氣。ide
開始佈局
首先是頁面的xaml代碼,其實比較簡單,就是一些Canvas裏面裝了些image和一個border(是做爲按鈕展開後的背景)。下面註釋的那個canvas是爲了看到懸浮窗在界面右邊的時的效果,方便作動畫添加的,讀者不用在乎動畫
要求懸浮按鈕能夠拖動,拖動後靠在自動屏幕邊上顯示,拖動的時候超過屏幕的中軸就靠在右邊,點擊按鈕向左邊以此展開按鈕,若是拖動後在屏幕中軸左邊則靠左側邊上,點擊屏幕向右依次展開,再次點擊收回按鈕。(展開按鈕的時候我有添加了個選擇動畫,旋轉了360度,)考慮到動畫須要變化,之前懸浮窗的中的按鈕位置也要根據拖放的位置動態變化,因此動畫和佈局都用代碼控制。this
<phone:PhoneApplicationPage.Resources> <Style x:Key="imageS" TargetType="Image"> <Setter Property="Width" Value="50"/> <Setter Property="Height" Value="50"/> <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/> </Style> <!--<Storyboard x:Name="Storyboard1"> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="border"> <EasingDoubleKeyFrame KeyTime="0" Value="0.04"/> <EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="1.003"/> </DoubleAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="border"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="0:0:0.4"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard>--> </phone:PhoneApplicationPage.Resources> <!--LayoutRoot 是包含全部頁面內容的根網格--> <Grid> <Grid.Background> <ImageBrush Stretch="Fill" ImageSource="/Assets/Image/bg1.jpg"/> </Grid.Background> <Canvas x:Name="HoverContentner" HorizontalAlignment="Left" Height="50" Margin="0,0,0,0" VerticalAlignment="Top" Width="300" > <Border Visibility="Collapsed" x:Name="border" Width="300" Height="47" HorizontalAlignment="Left" VerticalAlignment="Top" CornerRadius="12" Background="#B2D1DAC7" RenderTransformOrigin="0.0,0.0"> <Border.RenderTransform> <CompositeTransform/> </Border.RenderTransform> </Border> <Image x:Name="image0" Style="{StaticResource imageS}" Source="/Assets/Image/button1.png" Tap="image0_Tap" ManipulationDelta="image0_ManipulationDelta" ManipulationCompleted="image0_ManipulationCompleted" > <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> <Image Visibility="Collapsed" x:Name="image1" Style="{StaticResource imageS}" Canvas.Left="60" Source="/Assets/Image/button2.png" > <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> <Image Visibility="Collapsed" x:Name="image2" Style="{StaticResource imageS}" Canvas.Left="120" Source="/Assets/Image/button3.png"> <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> <Image Visibility="Collapsed" x:Name="image3" Style="{StaticResource imageS}" Canvas.Left="180" Source="/Assets/Image/button4.png"> <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> <Image Visibility="Collapsed" x:Name="image4" Style="{StaticResource imageS}" Canvas.Left="240" Source="/Assets/Image/button5.png" > <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> </Canvas> <!--<Canvas x:Name="HoverContentnerRight" HorizontalAlignment="Left" Height="50" Margin="180,300,0,0" VerticalAlignment="Top" Width="300"> <Image Visibility="Visible" Style="{StaticResource imageS}" Canvas.Left="180" Source="/Assets/Image/button2.png" > <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> <Image Visibility="Visible" Style="{StaticResource imageS}" Canvas.Left="120" Source="/Assets/Image/button3.png" > <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> <Image Visibility="Visible" Style="{StaticResource imageS}" Canvas.Left="60" Source="/Assets/Image/button4.png" > <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> <Image Visibility="Visible" Style="{StaticResource imageS}" Canvas.Left="0" Source="/Assets/Image/button5.png" > <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> <Image x:Name="image0left" Style="{StaticResource imageS}" Canvas.Left="240" Source="/Assets/Image/button1.png" Tap="image0_Tap" ManipulationDelta="image0_ManipulationDelta" ManipulationCompleted="image0_ManipulationCompleted" > <Image.RenderTransform> <CompositeTransform/> </Image.RenderTransform> </Image> </Canvas>--> </Grid> </phone:PhoneApplicationPage>
一些定義的變量spa
private int trasnlateLength = 60; private bool left = true; private bool lastleft = true;//lastleft上次 private Storyboard expandstory = null; private Storyboard hidestory = null; private bool isStoryBegin = true;
首先是處理拖動的代碼code
private void image0_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e) { if (image1.Visibility == Visibility.Visible) { } else { double oldleft = HoverContentner.Margin.Left; double oldtop = HoverContentner.Margin.Top; //if (!left && e.DeltaManipulation.Translation.X<0) //{ // oldleft += -e.DeltaManipulation.Translation.X; //} //else //{ // oldleft += e.DeltaManipulation.Translation.X; //} oldleft += e.DeltaManipulation.Translation.X; oldtop += e.DeltaManipulation.Translation.Y; // Debug.WriteLine("左邊距"+oldleft + "............... 右邊距"+ oldtop); HoverContentner.Margin = new Thickness(oldleft, oldtop, 0, 0); this.UpdateLayout(); } }
拖動完成後根據位置靠邊顯示orm
private void image0_ManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e) { if (e.TotalManipulation.Translation.X==0.0f&&e.TotalManipulation.Translation.Y==0.0f) { return; } // Debug.WriteLine(" HoverContentner.Margin.left: " + HoverContentner.Margin.Left); if (left &&HoverContentner.Margin.Left < 220) { HoverContentner.Margin = new Thickness(0, HoverContentner.Margin.Top, 0, 0); updateCanvas(true); } else if (left &&HoverContentner.Margin.Left > 220) { HoverContentner.Margin = new Thickness(185, HoverContentner.Margin.Top, 0, 0); updateCanvas(false); } else if (!left&&HoverContentner.Margin.Left > 0) { HoverContentner.Margin = new Thickness(185, HoverContentner.Margin.Top, 0, 0); updateCanvas(false); } else { HoverContentner.Margin = new Thickness(0, HoverContentner.Margin.Top, 0, 0); updateCanvas(true); } }
而後更新佈局blog
private void updateCanvas( bool isleft) { left = isleft; if (isleft) { // trasnlateLength = 60; Canvas.SetLeft(image0, 0); Canvas.SetLeft(image1, 60); Canvas.SetLeft(image2, 120); Canvas.SetLeft(image3, 185); Canvas.SetLeft(image4, 240); border.HorizontalAlignment = HorizontalAlignment.Left; border.RenderTransformOrigin = new Point(0, 0); } else { // trasnlateLength = -60; Canvas.SetLeft(image0, 240); Canvas.SetLeft(image1, 185); Canvas.SetLeft(image2, 120); Canvas.SetLeft(image3, 60); Canvas.SetLeft(image4, 0); border.HorizontalAlignment = HorizontalAlignment.Right; border.RenderTransformOrigin = new Point(1, 1); HoverContentner.Width = 300; //image1.Visibility = Visibility.Visible; //image2.Visibility = Visibility.Visible; //image3.Visibility = Visibility.Visible; //image4.Visibility = Visibility.Visible; UpdateLayout(); } }
點擊圖片時開始執行動畫,一個展開的和一個收回的動畫,若是上次懸浮窗的位置和此次的位置不一樣(上次在左邊,此次在右邊,則更新動畫)遊戲
private void image0_Tap(object sender, System.Windows.Input.GestureEventArgs e) { if (lastleft != left)//若是方向改變則刷新動畫 { expandstory = CreateExpand(); hidestory = HideExpand(); } if (isStoryBegin) { expandstory.Begin(); isStoryBegin = false; } else { hidestory.Begin(); isStoryBegin = true; } }
展開的動畫
private Storyboard CreateExpand() { Storyboard expand = new Storyboard(); #region 旋轉動畫 for (int i = 0; i < 5; i++) { //旋轉動畫 DoubleAnimationUsingKeyFrames rotation = new DoubleAnimationUsingKeyFrames(); Storyboard.SetTargetProperty(rotation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.Rotation)")); //只有動畫在xaml中才可使用這個方法 // Storyboard.SetTargetName(rotation, "image" + i); Storyboard.SetTarget(rotation, this.FindName("image" + i) as Image); EasingDoubleKeyFrame startAngle = new EasingDoubleKeyFrame(); startAngle.Value = -360; startAngle.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)); rotation.KeyFrames.Add(startAngle); if (i == 2) { rotation.BeginTime = TimeSpan.FromMilliseconds(50); } else if (i == 3) { rotation.BeginTime = TimeSpan.FromMilliseconds(100); } else if (i == 4) { rotation.BeginTime = TimeSpan.FromMilliseconds(150); } EasingDoubleKeyFrame endAngle = new EasingDoubleKeyFrame(); endAngle.Value = 0; endAngle.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300)); rotation.KeyFrames.Add(endAngle); expand.Children.Add(rotation); } #endregion for (int i = 1; i < 5; i++) { #region 平移動畫 //X軸平移 DoubleAnimationUsingKeyFrames xtranslate = new DoubleAnimationUsingKeyFrames(); Storyboard.SetTargetProperty(xtranslate, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateX)")); Storyboard.SetTarget(xtranslate, this.FindName("image" + i) as Image); //起始點 EasingDoubleKeyFrame xstartPoint = new EasingDoubleKeyFrame(); xstartPoint.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)); if (i == 1) { xstartPoint.Value = left ? -trasnlateLength : trasnlateLength; } else if (i == 2) { xtranslate.BeginTime = TimeSpan.FromMilliseconds(50); xstartPoint.Value = left ? -trasnlateLength * 2 : trasnlateLength * 2; } else if (i == 3) { xtranslate.BeginTime = TimeSpan.FromMilliseconds(100); xstartPoint.Value = left ? -trasnlateLength * 3 : trasnlateLength * 3; } else if (i == 4) { xtranslate.BeginTime = TimeSpan.FromMilliseconds(150); xstartPoint.Value = left ? -trasnlateLength * 4 : trasnlateLength * 4; ; } lastleft = left; xstartPoint.EasingFunction = new PowerEase() { EasingMode = 0 }; //終點 EasingDoubleKeyFrame xendPoint = new EasingDoubleKeyFrame(); xendPoint.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300)); xendPoint.Value = 0; xendPoint.EasingFunction = new PowerEase() { EasingMode = 0 }; xtranslate.KeyFrames.Add(xstartPoint); xtranslate.KeyFrames.Add(xendPoint); expand.Children.Add(xtranslate); #endregion #region 改變屬性值的動畫 //改變屬性值的動畫 ObjectAnimationUsingKeyFrames visi = new ObjectAnimationUsingKeyFrames(); Storyboard.SetTargetProperty(visi, new PropertyPath("(UIElement.Visibility)")); Storyboard.SetTarget(visi, this.FindName("image" + i) as Image); DiscreteObjectKeyFrame startObj = new DiscreteObjectKeyFrame(); startObj.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)); startObj.Value = Visibility.Visible; DiscreteObjectKeyFrame endObj = new DiscreteObjectKeyFrame(); endObj.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300)); endObj.Value = Visibility.Visible; if (i == 2) { visi.BeginTime = TimeSpan.FromMilliseconds(50); } else if (i == 3) { visi.BeginTime = TimeSpan.FromMilliseconds(100); } else if (i == 4) { visi.BeginTime = TimeSpan.FromMilliseconds(150); } visi.KeyFrames.Add(startObj); visi.KeyFrames.Add(endObj); expand.Children.Add(visi); #endregion } #region 縮放動畫 //X軸平移 DoubleAnimationUsingKeyFrames xtranslateb = new DoubleAnimationUsingKeyFrames(); Storyboard.SetTargetProperty(xtranslateb, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.ScaleX)")); Storyboard.SetTarget(xtranslateb, this.FindName("border" ) as Border); //起始點 EasingDoubleKeyFrame xstartPointb = new EasingDoubleKeyFrame(); xstartPointb.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)); xstartPointb.Value = 0.04f; xstartPointb.EasingFunction = new PowerEase() { EasingMode = 0 }; //終點 EasingDoubleKeyFrame xendPointb = new EasingDoubleKeyFrame(); xendPointb.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300)); xendPointb.Value = 1; xendPointb.EasingFunction = new PowerEase() { EasingMode = 0 }; xtranslateb.KeyFrames.Add(xstartPointb); xtranslateb.KeyFrames.Add(xendPointb); expand.Children.Add(xtranslateb); #endregion #region 改變border屬性值的動畫 //改變屬性值的動畫 ObjectAnimationUsingKeyFrames visib = new ObjectAnimationUsingKeyFrames(); Storyboard.SetTargetProperty(visib, new PropertyPath("(UIElement.Visibility)")); Storyboard.SetTarget(visib, this.FindName("border") as Border); DiscreteObjectKeyFrame startObjb = new DiscreteObjectKeyFrame(); startObjb.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)); startObjb.Value = Visibility.Visible; DiscreteObjectKeyFrame endObjb = new DiscreteObjectKeyFrame(); endObjb.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300)); endObjb.Value = Visibility.Visible; visib.KeyFrames.Add(startObjb); visib.KeyFrames.Add(endObjb); expand.Children.Add(visib); #endregion return expand; }
還有個收縮的動畫就不給你們貼出來了,留給你們一個本身動手的過程。哇咔咔,下面貼張動態圖,吸引下諸位眼球。