ReusableFollowExample.axaml代碼
<UserControl xmlns="https://github.com/avaloniaui" 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" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" xmlns:local="using:AvaloniaUI" x:Class="AvaloniaUI.ReusableFollowExample"> <Canvas Background="Transparent"> <!-- 紅色方塊 --> <local:FollowMouseCanvas Canvas.Left="0" Canvas.Top="0" Width="50" Height="50" Background="Red"> <!-- 可以在這里放更多內容 --> </local:FollowMouseCanvas> <!-- 綠色方塊 --> <local:FollowMouseCanvas Canvas.Left="300" Canvas.Top="0" Width="50" Height="50" Background="Green"> </local:FollowMouseCanvas> <!-- 藍色方塊 --> <local:FollowMouseCanvas Canvas.Left="0" Canvas.Top="300" Width="50" Height="50" Background="Blue"> </local:FollowMouseCanvas> </Canvas> </UserControl>
ReusableFollowExample.axaml.cs代碼
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.VisualTree;
using Shares.Avalonia;
using System;
namespace AvaloniaUI;
public class FollowMouseCanvas : Canvas
{
private Vector velocity;
private Point lastMouse;
private Canvas? parentCanvas;
private readonly AnimationPlayer player = new AnimationPlayer();
public FollowMouseCanvas()
{
player.Fps = 60;
player.Loop = true;
player.Duration = double.MaxValue;
player.At(0).PlayGlobal(UpdatePosition);
this.AttachedToVisualTree += (_, __) =>
{
EnsureParent();
player.Start();
};
}
private void EnsureParent()
{
parentCanvas = this.GetVisualParent() as Canvas;
if (parentCanvas != null)
{
parentCanvas.PointerMoved += OnPointerMoved;
}
}
private void OnPointerMoved(object? sender, PointerEventArgs e)
{
if (parentCanvas != null)
lastMouse = e.GetPosition(parentCanvas);
}
private void UpdatePosition(double progress)
{
if (parentCanvas == null)
return;
double left = Canvas.GetLeft(this);
double top = Canvas.GetTop(this);
if (double.IsNaN(left)) left = 0;
if (double.IsNaN(top)) top = 0;
var location = new Point(left, top);
var toMouse = lastMouse - location;
// 根據 progress 做周期性調制,比如讓速度在一個周期中變化
double followForce = 0.01 + 0.005 * Math.Sin(progress * 2 * Math.PI * 2); // 2Hz波動
double drag = 0.8 + 0.1 * Math.Sin(progress * 2 * Math.PI); // 阻尼輕微變化
velocity += toMouse * followForce;
velocity *= drag;
location += velocity;
Canvas.SetLeft(this, location.X);
Canvas.SetTop(this, location.Y);
}
}
public partial class ReusableFollowExample : UserControl
{
public ReusableFollowExample()
{
InitializeComponent();
}
}
運行效果

浙公網安備 33010602011771號