win10 UWP 蜘蛛網效果
我看見了知乎首頁登錄背景和普通的地球人寫的博客,發現了個好看的效果。
那麽我來告訴大家如何做這個效果。
第一步是在 Canvas 畫點,第二步是讓點移動,第三步是畫線
在 Canvas 畫一個點
我們畫點可以使用 Ellipse 我們給他寬和高,Fill,就可以畫出來。需要加在 Canvas ,可以使用canvas.Children.Add(ellipse)
Canvas 一開始的大小是 0 ,需要一開始給他一個足夠大的值
<Canvas x:Name="P" Width="1000" Height="1000"/>
於是給他一個比較大的值,超過外面的Grid就不顯示。
添加 一個 Ellipse 就會顯示,可以沒有指定在哪顯示,也就是顯示的 X 和 Y。
指定添加到 Canvas 的 Element 的位置
我們可以通過幾個方法改變控件的位置,在我之前寫的拖動控件博客有說到。
現在使用 Canvas,可以使用 Canvas 有的一個方法。
假如有一個 X 和 Y 要設置在控件,那麽可以使用
Canvas.SetLeft(control, X );
Canvas.SetTop(control, Y);
註意,Canvas 是類。
這個方法可以移動控件。
我就是用他移動點。
隨機移動點
我首先寫一個類,Staf。包含顯示的 Point 和他的 X,Y,兩個方向移動速度。還有移動多久,超過了可以移動的時間,就隨機給新移動速度。
public class Staf
{
public UIElement Point { set; get; }
public double X { set; get ; }
public double Y { set; get; }
public double Vx { set; get; }
public double Vy { set; get; }
public void RandomStaf(Random ran)
{
var staf = this;
_ran = ran;
staf.Vx = (double)ran.Next(-1000, 1000) / 1000;
staf.Vy = (double)ran.Next(-1000, 1000) / 1000;
staf.Time = ran.Next(100);
}
private Random _ran;
public int Time
{
set
{
_time = value;
if (value == 0)
{
RandomStaf(_ran);
}
}
get
{
return _time;
}
}
private int _time;
}
畫線
使用兩重 foreach ,得到兩個點之間距離,如果距離小於我給的一個值,那麽就是可以連線
那麽距離長的就把連線的寬度變短。
這個做法很簡單,可以使用 StrokeThickness 設置線寬度。
line.StrokeThickness=最大寬度 * (最大距離-距離)/最大距離
線需要多少個點可以確定?這個我就不說啦,確定了兩個點是可以連線,於是使用就可以設置線的點。需要知道,點的X和Y是左上角,需要加上畫的圖形的值才是連在點,不然看起來不是連在點。
自動移動
可以使用 DispatcherTimer ,過 0.1 s就移動點和畫線。
public MainPage()
{
this.InitializeComponent();
_time = new DispatcherTimer();
_time.Interval = TimeSpan.FromTicks(500);
_time.Tick += Time_Tick;
_time.Start();
}
private DispatcherTimer _time
Time_Tick就寫移動點和線的代碼
全部代碼
<Page
x:Class="Bsgame.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Bsgame"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Canvas x:Name="P" Width="1000" Height="1000">
</Canvas>
<Canvas x:Name="Pw" Width="1000" Height="1000"></Canvas>
</Grid>
</Page>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;
namespace Bsgame
{
/// <summary>
/// 可用於自身或導航至 Frame 內部的空白頁。
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
_time = new DispatcherTimer();
_time.Interval = TimeSpan.FromTicks(500);
_time.Tick += Time_Tick;
RandomStaf();
_time.Start();
_width = Window.Current.Bounds.Width;
_height = Window.Current.Bounds.Height;//lindexi
}
private void RandomStaf()
{
const int count = 20;
for (int i = 0; i < count; i++)
{
Staf staf = new Staf();
staf.X = ran.Next((int)_width);
staf.Y = ran.Next((int)_height);
staf.Point = new Ellipse()
{
Height = 10,
Width = 10,
Fill = new SolidColorBrush(Colors.Gray),
};
staf.RandomStaf(ran);
// CSDN
_staf.Add(staf);
}
foreach (var temp in _staf)
{
P.Children.Add(temp.Point);
//lindexi
}
}
private List<Staf> _staf = new List<Staf>();
private double _width;
private double _height;
private void Time_Tick(object sender, object e)
{
foreach (var temp in _staf)
{
if (temp.X > _width || temp.Y > _height
|| temp.X < 0 || temp.Y < 0)
{
temp.X = ran.Next((int)_width);
temp.Y = ran.Next((int)_height);
}//lindexi.oschina.io
temp.X -= temp.Vx;
temp.Y -= temp.Vy;
Canvas.SetLeft(temp.Point, temp.X);
Canvas.SetTop(temp.Point, temp.Y);
temp.Time--;
}
const double distan = 200;
Pw.Children.Clear();
Line line = new Line();
foreach (var temp in _staf)
{
foreach (var p in _staf)
{
line.X1 = temp.X + 5;
line.Y1 = temp.Y + 5;
line.X2 = p.X + 5;
line.Y2 = p.Y + 5;
double sqrt = Math.Sqrt(Math.Pow((line.X1 - line.X2), 2) +
Math.Pow((line.Y1 - line.Y2), 2));
if (sqrt < distan)
{
line.Stroke = new SolidColorBrush(Colors.Gray);
line.StrokeThickness = 5* (distan- sqrt) /distan;
Pw.Children.Add(line);
line = new Line();
}
}
}
}
private Random ran = new Random();
private DispatcherTimer _time;
}
public class Staf
{
public UIElement Point { set; get; }
public double X { set; get; }
public double Y { set; get; }
public double Vx { set; get; }
public double Vy { set; get; }
public void RandomStaf(Random ran)
{
var staf = this;
_ran = ran;
staf.Vx = (double)ran.Next(-1000, 1000) / 1000;
staf.Vy = (double)ran.Next(-1000, 1000) / 1000;
staf.Time = ran.Next(100);
}
private Random _ran;
public int Time
{
set
{
_time = value;
if (value == 0)
{
RandomStaf(_ran);
}
}
get
{
return _time;
}
}
private int _time;
}
}
可以看到性能很差,於是把連線去掉,顯示點不顯示連接
private void RandomStaf(object sender, object e)
{
Storyboard board = new Storyboard();
board.Duration = new Duration(TimeSpan.FromSeconds(1));
board.Completed += RandomStaf;
DoubleAnimationUsingKeyFrames animation;
foreach (var temp in _staf)
{
double f = temp.X;
temp.X += temp.Vx * 10;
if (temp.X > _width - 100)
{
temp.X = _width - 100;
}
else if (temp.X < 0)
{
temp.X = 0;
}
animation = EllPoile(f, temp.X);
Storyboard.SetTarget(animation, temp.Point);
Storyboard.SetTargetProperty(animation, "(Canvas.Left)");
board.Children.Add(animation);
f = temp.Y;
temp.Y += temp.Vy * 10;
if (temp.Y > _height - 100)
{
temp.Y = _height - 100;
}
else if (temp.Y < 0)
{
temp.Y = 0;
}
animation = EllPoile(f, temp.Y);
Storyboard.SetTarget(animation, temp.Point);
Storyboard.SetTargetProperty(animation, "(Canvas.Top)");
if (temp.X >= _width - 100 || temp.Y >= _height - 100
|| temp.X <= 0 || temp.Y <= 0)
{
temp.X = ran.Next((int)_width);
temp.Y = ran.Next((int)_height);
}
board.Children.Add(animation);
temp.Time -= 10;
animation = EllPoile(10, 15);
Storyboard.SetTarget(animation, temp.Point);
Storyboard.SetTargetProperty(animation, "Height");
board.Children.Add(animation);
animation = EllPoile(10, 15);
Storyboard.SetTarget(animation, temp.Point);
Storyboard.SetTargetProperty(animation, "Width");
board.Children.Add(animation);
animation = new DoubleAnimationUsingKeyFrames();
EasingDoubleKeyFrame frame = new EasingDoubleKeyFrame();
frame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
frame.Value = 0;
animation.KeyFrames.Add(frame);
frame = new EasingDoubleKeyFrame();
frame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5));
frame.Value = 180;
animation.KeyFrames.Add(frame);
frame = new EasingDoubleKeyFrame();
frame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
frame.Value = 0;
animation.KeyFrames.Add(frame);
Storyboard.SetTarget(animation, temp.Point.RenderTransform);
Storyboard.SetTargetProperty(animation, "(CompositeTransform.Rotation)");
board.Children.Add(animation);
}
board.Begin();
}
本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名林德熙(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發布。如有任何疑問,請與我聯系。
win10 UWP 蜘蛛網效果