實現效果:此方框實現每幀改變一次顏色canvas
private readonly Random _rand = new Random(); public SimpleExample() { CompositionTarget.Rendering += UpdateColor; } private void UpdateColor(object sender, EventArgs e) { // Set a random color animatedBrush.Color = Color.FromRgb((byte) _rand.Next(255), (byte) _rand.Next(255), (byte) _rand.Next(255)); }
在Page每幀呈現的方法中獲取當前方框的座標與當前鼠標座標差量值,設置每幀方框往鼠標點移動一點點距離。造成方框慢慢跟隨到鼠標的效果。緩存
public partial class FollowExample : Page
{dom
private Point _lastMousePosition = new Point(0, 0); private Vector _rectangleVelocity = new Vector(0, 0); public FollowExample() { CompositionTarget.Rendering += UpdateRectangle; PreviewMouseMove += UpdateLastMousePosition; } private void UpdateRectangle(object sender, EventArgs e) { var location = new Point(Canvas.GetLeft(followRectangle), Canvas.GetTop(followRectangle)); //find vector toward mouse location var toMouse = _lastMousePosition - location; //add a force toward the mouse to the rectangles velocity var followForce = 0.01; _rectangleVelocity += toMouse*followForce; //dampen the velocity to add stability var drag = 0.8; _rectangleVelocity *= drag; //update the new location from the velocity location += _rectangleVelocity; //set new position Canvas.SetLeft(followRectangle, location.X); Canvas.SetTop(followRectangle, location.Y); } private void UpdateLastMousePosition(object sender, MouseEventArgs e) { _lastMousePosition = e.GetPosition(containerCanvas); }
}動畫
實現效果:this
代碼此處增長一個字段:時間間隔值TimeSpan _lastRender,目的是獲取幀間隔時間值。其餘同上spa
public partial class FrameIndependentFollowExample : Page { private Point _lastMousePosition = new Point(0, 0); //timing variables private TimeSpan _lastRender; private Vector _rectangleVelocity = new Vector(0, 0); public FrameIndependentFollowExample() { InitializeComponent(); _lastRender = TimeSpan.FromTicks(DateTime.Now.Ticks); CompositionTarget.Rendering += UpdateRectangle; PreviewMouseMove += UpdateLastMousePosition; } private void UpdateLastMousePosition(object sender, MouseEventArgs e) { _lastMousePosition = e.GetPosition(containerCanvas); }
此處與上例變化主要是幀間位移差量的計算,主要與參數(幀間時間值)有關。線程
private void UpdateRectangle(object sender, EventArgs e) { var location = new Point(Canvas.GetLeft(followRectangle), Canvas.GetTop(followRectangle)); //find vector toward mouse location var toMouse = _lastMousePosition - location; //add a force toward the mouse to the rectangles velocity var followForce = 0.01; _rectangleVelocity += toMouse*followForce; //dampen the velocity to add stability var drag = 0.8; _rectangleVelocity *= drag; //update the new location from the velocity location += _rectangleVelocity; //set new position Canvas.SetLeft(followRectangle, location.X); Canvas.SetTop(followRectangle, location.Y); }
實現效果:
1.跟隨鼠標方框爲3個,這些都繼承同一個Canvas,都是先搖擺跟隨功能效果。
xaml代碼:3d
<Canvas Background="transparent"> <perFrameAnimation:FollowMouseCanvas Canvas.Left="0" Canvas.Top="0" Background="red" Width="50" Height="50"> <!-- could put more content that will also follow mouse here--> </perFrameAnimation:FollowMouseCanvas> <perFrameAnimation:FollowMouseCanvas Canvas.Left="300" Canvas.Top="0" Background="green" Width="50" Height="50"> <!-- could put more content that will also follow mouse here--> </perFrameAnimation:FollowMouseCanvas> <perFrameAnimation:FollowMouseCanvas Canvas.Left="0" Canvas.Top="300" Background="blue" Width="50" Height="50"> <!-- could put more content that will also follow mouse here--> </perFrameAnimation:FollowMouseCanvas> </Canvas>
繼承Canvas,實現搖擺跟隨功能:code
public class FollowMouseCanvas : Canvas { private TimeSpan _lastRender; private Canvas _parentCanvas; private Point _parentLastMousePosition = new Point(0, 0); private Vector _velocity = new Vector(0, 0); public FollowMouseCanvas() { //_lastRender = TimeSpan.FromTicks(DateTime.Now.Ticks);//註釋掉是由於初始值太大,最後location差值過大而一開始不會顯示綠色與藍色方框。 CompositionTarget.Rendering += UpdatePosition; } private void UpdatePosition(object sender, EventArgs e) { var renderingArgs = (RenderingEventArgs) e; var deltaTime = (renderingArgs.RenderingTime - _lastRender).TotalSeconds; _lastRender = renderingArgs.RenderingTime; if (_parentCanvas == null) { _parentCanvas = VisualTreeHelper.GetParent(this) as Canvas; if (_parentCanvas == null) { //parent isnt canvas so just abort trying to follow mouse CompositionTarget.Rendering -= UpdatePosition; } else { //parent is canvas, so track mouse position and time _parentCanvas.PreviewMouseMove += UpdateLastMousePosition; } } //get location var location = new Point(GetLeft(this), GetTop(this)); //check for NaN's and replace with 0,0 if (double.IsNaN(location.X) || double.IsNaN(location.Y)) location = new Point(0, 0); //find vector toward mouse location var toMouse = _parentLastMousePosition - location; //add a force toward the mouse to the rectangles velocity var followForce = 1.0; _velocity += toMouse*followForce; //dampen the velocity to add stability var drag = 0.95; _velocity *= drag; //update the new location from the velocity location += _velocity*deltaTime; //set new position SetLeft(this, location.X); SetTop(this, location.Y); } private void UpdateLastMousePosition(object sender, MouseEventArgs e) { if (_parentCanvas == null) return; if (this.Background==Brushes.Blue) { _parentLastMousePosition.X = e.GetPosition(_parentCanvas).X+100; _parentLastMousePosition.Y = e.GetPosition(_parentCanvas).Y; } else if (this.Background== Brushes.Green) { _parentLastMousePosition.X = e.GetPosition(_parentCanvas).X - 100; _parentLastMousePosition.Y = e.GetPosition(_parentCanvas).Y; } else { _parentLastMousePosition = e.GetPosition(_parentCanvas); } } }
見第2章對象
擴展:
CompositionTarget類:表示您的應用程序的顯示圖面。
HwndTarget 類:表示到支持可視化撰寫的窗口句柄的綁定。
VisualTarget 類:提供用於跨越線程邊界將一個可視化樹鏈接到另外一個可視化樹的功能。
RenderingEventArgs 類:Rendering 事件的必需參數。