WPF动画牵引小球

开发工具与关键技术:WPF

形状绘图:先绘制出圆形给圆形背景颜色

xaml代码如下:

<Window x:Class="DragABall.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="拉力小球"
        Height="480" Width="640" 
        Loaded="Window_Loaded" 
        MouseLeftButtonUp="Window_MouseLeftButtonUp">
    <Grid Name="layout">
        <StackPanel Orientation="Horizontal" VerticalAlignment="Top">
            <Label Content="流体粘性系数:"></Label>
            <TextBox Name="tbx_Eta" Text="100"></TextBox>
            <Label Content="小球密度:"></Label>
            <TextBox Name="tbx_Rho" Text="1"></TextBox>
        </StackPanel>
        <Ellipse Stroke="Pink" x:Name="moveObj" Width="64" Height="64" Fill="#93D6CC"></Ellipse>
    </Grid>
</Window>

效果图如下:
在这里插入图片描述

xaml.cs代码如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DragABall
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        #region 成员变量
        /// <summary>
        /// 上次绘制时的速度
        /// </summary>
        private Vector v1 = new Vector(0, 0);
        /// <summary>
        /// 与上次绘制时间的时间间隔
        /// </summary>
        private TimeSpan prevTime = TimeSpan.Zero;
        /// <summary>
        /// 鼠标点击 相对于小球的位置
        /// </summary>
        private Point point = new Point(0, 0);
        /// <summary>
        /// 计时器
        /// </summary>
        private Stopwatch stopwatch = new Stopwatch();
        /// <summary>
        /// 绘制拉力线
        /// </summary>
        private Line line = new Line();
        /// <summary>
        /// 鼠标点相对于布局元素
        /// </summary>
        private Point pMouse = new Point(0, 0);
        #endregion

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //给对象加一个平移转换
            this.moveObj.RenderTransform = new TranslateTransform();
            //开始计时
            this.stopwatch.Start();
            //每一帧绘制
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
            //线
            line.StrokeThickness = 2;
            line.Stroke = System.Windows.Media.Brushes.Red;
            layout.Children.Add(line);
        }

        private void Window_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            //鼠标相对于小方块的位置
            point = e.GetPosition(this.moveObj);
            //由于改相对位置是相对于小方块左上角的,将其纠正到相当于小球中心
            point.Offset(-this.moveObj.ActualWidth / 2, -this.moveObj.ActualHeight / 2);
            //鼠标点相对于布局元素
            pMouse = e.GetPosition(this.layout);
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            //粘滞阻力
            //在理论力学中所说的"与物体速度一次方成正比的阻力"指的就是粘滞阻力 在空气中运动速度不十分快的物体 受到的阻力主要是粘滞阻力
            //斯托克斯公式 球形物体 F=6πηvr=3πηvd η为流体的粘性系数 r为球形物体的半径 d为球形物体的直径
            //加速度a=(v2-v1)/t 速度差v2-v1=at
            //F=F拉-F阻=ma
            //速度差v2-v1=at=((F拉-F阻)/m)t=((F拉-3πηv1d)/m)t
            //球体质量=4/3 * π * r^3 * ρ=1/6* π * d^3 * ρ
            //s=vt+1/2at^2

            //时间 t
            TimeSpan currentTime = this.stopwatch.Elapsed;
            double t = (currentTime - this.prevTime).TotalSeconds;
            this.prevTime = currentTime;
            //使用鼠标相对于小方块的位置作为拉力 F拉
            Vector F= new Vector(point.X, point.Y);
            //流体的粘性系数 η
            double eta = 100;
            if (!string.IsNullOrEmpty(this.tbx_Eta.Text))
                double.TryParse(this.tbx_Eta.Text, out eta);
            //直径 d
            double d = this.moveObj.Width;
            //小球密度 ρ
            double rho = 1;
            if (!string.IsNullOrEmpty(this.tbx_Rho.Text))
                double.TryParse(this.tbx_Rho.Text, out rho);
            //小球质量 m
            double m = (Math.PI * d * d * d * rho) / 6;
            //为了能拉动小球 自定义个拉力系数 拉小球需要的力和小球质量m成正比和小球直径d的三次方成正比
            double coefficient = d * d * d;
            F= coefficient * F;
            //速度差v2-v1=((F拉-3πηv1d)/m)t
            Vector vDiff = ((F- 3 * Math.PI * eta * v1 * d) / m) * t;
            //s=v1t+1/2at^2=v1t+(1/2)((v2-v1)/t)*t*t=v1t+(1/2)(v2-v1)*t
            Vector s = v1 * t + (vDiff * t) / 2;

            //小球移动
            TranslateTransform translate = (TranslateTransform)this.moveObj.RenderTransform;
            translate.X += s.X;
            translate.Y += s.Y;
            //新的相对位置
            point.X -= s.X;
            point.Y -= s.Y;
            //记录本次速度
            //v2=vDiff+v1
            Vector v2 = vDiff + v1;
            v1 = v2;
            //绘制线
            line.X1 = pMouse.X;
            line.Y1 = pMouse.Y;
            line.X2 = pMouse.X - point.X;
            line.Y2 = pMouse.Y - point.Y;
        }
    }
}

最后效果图如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值