zoukankan      html  css  js  c++  java
  • 用Reactive Extensions快速实现鼠标手势功能

    鼠标手势非常方便,在很多程序中得到了广泛应用。在这里我要介绍一种通过用Reactive Extensions快速实现鼠标手势功能的方法,以供有需要的朋友参考。

    一般用的那些只有上下左右的鼠标手势的识别原理并不复杂,只需要对鼠标轨迹进行定点采集,根据偏移的角度进行降噪处理,折换成上下左右四个方向即可。具体代码可以参考下文中的GetDirection方法(这个函数不是我写的,以前在网上找的,原始出处不记得了)。通过用Reactive extensions可以非常容易的实现这一过程。具体代码如下: 

    public partial class Form1 : Form
    {
        
    public Form1()
        {
            InitializeComponent();

            Process();
        }

        
    private void Process()
        {
            var mouseDown 
    = Observable.FromEventPattern<MouseEventArgs>(this"MouseDown");
            var mouseMove 
    = Observable.FromEventPattern<MouseEventArgs>(this"MouseMove");
            var mouseUp 
    = Observable.FromEventPattern<MouseEventArgs>(this"MouseUp");

            var mousePath 
    = mouseMove.SkipUntil(mouseDown).TakeUntil(mouseUp).Select(i => i.EventArgs.Location);

            mousePath.Take(
    1).Subscribe(_ => { }, () => label1.Text = "waitting for mouse up...");
            ProcessMouseGesture(mousePath);
        }


        
    void ProcessMouseGesture(IObservable<Point> mousePath)
        {
            
    //这里只是取0.1秒间隔作为采集点,不是很合适,还要把距离拿来一起算可能更精确一些
            var points = mousePath.Sample(TimeSpan.FromSeconds(0.1));

            var directions 
    = (from direction in points.Zip(points.Skip(1), (p1, p2) => GetDirection(p1, p2))
                                
    where direction != MouseGestureDirection.Unknown
                                select direction).DistinctUntilChanged();

            var directionList 
    = new List<MouseGestureDirection>();
            directions.Subscribe(d 
    => directionList.Add(d), () =>
                {
                    label1.Text 
    = string.Join(",", directionList.ToArray());
                    Process();
                });
        }

        
    static MouseGestureDirection GetDirection(Point start, Point end)
        {
            
    const double maxAngleError = 30;

            
    int deltaX = end.X - start.X;
            
    int deltaY = end.Y - start.Y;

            
    double length = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);

            
    double sin = deltaX / length;
            
    double cos = deltaY / length;

            
    double angle = Math.Asin(Math.Abs(sin)) * 180 / Math.PI;

            
    if ((sin >= 0&& (cos < 0))
                angle 
    = 180 - angle;
            
    else if ((sin < 0&& (cos < 0))
                angle 
    = angle + 180;
            
    else if ((sin < 0&& (cos >= 0))
                angle 
    = 360 - angle;

            
    //direction recognition
            if ((angle > 360 - maxAngleError) || (angle < 0 + maxAngleError))
                
    return MouseGestureDirection.Down;
            
    else if ((angle > 90 - maxAngleError) && (angle < 90 + maxAngleError))
                
    return MouseGestureDirection.Right;
            
    else if ((angle > 180 - maxAngleError) && (angle < 180 + maxAngleError))
                
    return MouseGestureDirection.Up;
            
    else if ((angle > 270 - maxAngleError) && (angle < 270 + maxAngleError))
                
    return MouseGestureDirection.Left;
            
    else return MouseGestureDirection.Unknown;
        }
    }


    enum MouseGestureDirection
    {
        Unknown,
        Up,
        Right,
        Down,
        Left
    }

    由于我对Reactive Extensions不熟,只是偶尔有空的时候看了看,目前还属于管中窥豹阶段,上述代码并非最佳实践,本文这里只是给出了一种思路和方法,如果谁有更合适的实现,欢迎留言指正。

  • 相关阅读:
    vue----计算与监听属性
    vue---条件与循环语句
    vue--模板语法
    git版本控制系统--介绍
    HttpWebRequest使用总结
    计算机专业的书普遍都这么贵,你们都是怎么获取资源的?
    130 个相见恨晚的超实用网站,一次性分享出来
    实现客户端与服务端的HTTP通讯
    默认网关(地址)
    .NET Reactor使用教程(加密源代码示例)
  • 原文地址:https://www.cnblogs.com/TianFang/p/2135633.html
Copyright © 2011-2022 走看看