【问题标题】:How I can recreate this MouseMove effect?如何重新创建此 MouseMove 效果?
【发布时间】:2011-08-19 09:55:00
【问题描述】:

我正在使用视差滚动技术在WPF 中开发一个表单,我需要完成最后一步。我希望重新创建this nice effect of the mouse

我正在尝试在鼠标完成移动时获得很酷的延迟缓动。当鼠标完成移动后,背景会慢慢停止移动,这很容易通过缓动点来实现,但我不知道如何做到这一点。

我创建了 3 个背景,当鼠标移动时,我重新创建了视差滚动。现在我希望添加此功能以使其更加逼真。

你知道如何重现鼠标的这种效果吗?

编辑

我列出了我的代码 sn-p 来向你展示当鼠标移动事件时我是如何移动这 3 个背景的:

private void Window_MouseMove(object sender, MouseEventArgs e)//it is the Layout Root that contain the 3 layouts to create the parallax effect
    {
        Point mouse = e.GetPosition(this);

        TransformGroup group = (TransformGroup)this.grid.RenderTransform; //The first Background

        TranslateTransform translate = (TranslateTransform)group.Children[3];

        translate.X = 400 - mouse.X ;

        translate.Y = 300 - mouse.Y;


        TransformGroup group1 = (TransformGroup)this.grid1.RenderTransform;// 2th Background

        TranslateTransform translate1 = (TranslateTransform)group1.Children[3];

        translate1.X = 400 - (mouse.X - 10) * 2;

        translate1.Y = 300 - (mouse.Y - 10) * 2;


        TransformGroup group2 = (TransformGroup)this.grid2.RenderTransform;// 3th Background

        TranslateTransform translate2 = (TranslateTransform)group2.Children[3];

        translate2.X = 400 - (mouse.X - 20) * 3;

        translate2.Y = 300 - (mouse.Y - 20) * 3;

    }

也许这能让你更好地理解我的问题。

【问题讨论】:

    标签: c# .net wpf mouseevent


    【解决方案1】:

    试试这个,有一个 Timer 会重复调用你的 mouseMove 方法 我稍作修改以调用实际返回延迟 mousePos 的 GetPos 方法。

    这应该让你开始。

        public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
        }
    
        private void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer( System.Windows.Threading.DispatcherPriority.Render);
            dispatcherTimer.Tick += new EventHandler(DispatcherTimer_Tick);
            dispatcherTimer.Interval = new TimeSpan(0,0,0,0,15);
            dispatcherTimer.Start();
        }
    
        double precision = 0.025;
    
        Point GetPos (Point pt, Point target, double speed) 
        { 
            double xdif = target.X-pt.X; 
            double ydif = target.Y-pt.Y; 
            if (xdif>=-precision && xdif<=precision)    pt.X = target.X;
            else                                        pt.X += (target.X-pt.X)*speed; 
    
            if (ydif>=-precision && ydif<=precision)    pt.Y = target.Y;    
            else                                        pt.Y += (target.Y-pt.Y)*speed;  
            return  pt; 
        }
    
        double speed                                        = 0.1;
        Point mouse = new Point();
        private void DispatcherTimer_Tick(object sender, EventArgs e)
        {
            Point mousePos                                  = Mouse.GetPosition(this); // change 'this' to a transparent element over your view if needed
            mouse = GetPos (mouse, mousePos, speed);
    
            TransformGroup group = (TransformGroup)this.grid.RenderTransform; 
            TranslateTransform translate = (TranslateTransform)group.Children[3];
            translate.X = 400 - mouse.X ;
            translate.Y = 300 - mouse.Y;
    
            TransformGroup group1 = (TransformGroup)this.grid1.RenderTransform;
            TranslateTransform translate1 = (TranslateTransform)group1.Children[3];
            translate1.X = 400 - (mouse.X - 10) * 2;
            translate1.Y = 300 - (mouse.Y - 10) * 2;
    
            TransformGroup group2 = (TransformGroup)this.grid2.RenderTransform;// 3th Background
            TranslateTransform translate2 = (TranslateTransform)group2.Children[3];
            translate2.X = 400 - (mouse.X - 20) * 3;
            translate2.Y = 300 - (mouse.Y - 20) * 3;
        }
    
    }
    

    【讨论】:

    • 嘿,戴夫,你的代码 sn-p 是如此正确。我可以重现上面链接的相同鼠标效果!!!非常感谢戴夫,祝您有愉快的一天
    【解决方案2】:

    你基本上需要引入一个速度的概念。

    当您开始移动鼠标时,您不仅需要“跟随鼠标”,还需要使用鼠标的移动和速度来创建移动速度。然后你可以有一个计时器来做这个动作。

    当鼠标停止时,你会有一个速度。然后,您的计时器可以根据当前速度保持运动,并根据一些阻尼率让速度快速降低。这将产生减速的效果。

    【讨论】:

    • 他的方法的问题是它可能不同步。他的例子清楚地表明背景被锁定(虽然速度较慢)到鼠标位置
    • 我通过将加速度映射到 Sin 曲线来完成这种事情。一点点三角可以得到你想要的曲线形状(从 0 到 1 而不是 -1 到 1 等)给你一个值,当你接近 0 时,你可以使用它来平滑地降低你的速度。
    • 棘手的部分是鼠标可以在任何时候再次开始移动....使用您的 sin 方法再次加速背景是困难的,因为它可能是延迟 sin 的一半,而它再次必须再次加速。看看我的方法(其他答案),它更简单,也适用于这些情况
    【解决方案3】:

    很简单:

    假设 mouseX 和 mouseY 是实际的鼠标值。然后背景应该例如移动到 backX, backY 这可能是这样的:

     backX = -mouseX/2;    //background moves in opposite direction and with half the speed of the mouse
     backY = -mouseY/2;
    

    但要获得流畅的运动,您无需直接设置变量,而是这样做:

     destBackX = -mouseX/2;  //actual position we want the background to move to
     destBackY = -mouseY/2;
    

    并且对于每一帧(每秒 30 帧或更快)我们计算此时的背景位置:

     backX += (destBackX - backX)/DELAY;   //backX is now eased to the final position destBackX
     backY += (destBackY - backY)/DELAY;
    

    延迟可以设置为 2 到 16 之间的任意值。值越高,它跟随你的动作越慢。

    【讨论】:

    • 嗨 Reineir 感谢您的回复,我想知道您对 destBack 指的是什么?非常感谢
    • destbacklx 和 destbacky 是背景最终应该移动到的坐标。 backx 和 backy 是背景当前所在的坐标。它正在向目标坐标(destbackx 和 destbacky)移动的每一帧
    • 我刚刚看到你的编辑...你填写 translate.x 和 translate.y 位置的地方你基本上是在设置背景的位置。现在不要直接这样做,而是将这些值放在 destBsckX 和 destBackY 中(只是您声明的一些变量)。现在添加一个计时器功能(每秒 30 次)并在其中添加我示例的最后 2 行。您使用 translate.x 和 translate.y,而不是我的示例中的 backX 和 backY。对于所有其他图层,您采用相同的方法,只需先从其中一个背景图层开始即可正确处理
    • 嗨 renier 我试图按照你的方式进行操作,但我无法解决,我一直卡在添加计时器功能。干杯
    • 看看这篇短文 om 如何添加定时器功能。 codeguru.com/csharp/sample_chapter/article.php/c7763 第二个清单是我的意思是计时器功能。我会将延迟设置为 30 或 50。在计时器的回调中,您将更新背景的变换
    猜你喜欢
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 2015-06-24
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多