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

  • 相关阅读:
    11 MySQL视图
    10 MySQL索引选择与使用
    08 MySQL存储引擎
    09 MySQL字符集
    06 MySQL运算符
    07 MySQL常用内置函数
    05 MySQL数据类型的选择与使用
    04 MySQL数据类型
    js 当前日期后7天
    md5加密
  • 原文地址:https://www.cnblogs.com/TianFang/p/2135633.html
Copyright © 2020-2023  润新知