65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 jQuery 和 JavaScript 捕获客户端鼠标事件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (3投票s)

2013 年 9 月 17 日

CPOL

2分钟阅读

viewsIcon

20537

用于捕获客户端鼠标事件的 JavaScript 库。

引言

我见过几个允许你捕获特定事件的客户端库——单击、双击、三击。但是,我需要一个更强大的库,它能够提供可配置的鼠标释放事件。这个 JavaScript 库就是这个需求的产物。

与其自己编写代码来捕获各种鼠标事件,并处理如何区分双击与两个单击,甚至三击的问题,不如使用这段代码来完成。

背景   

我需要编写一个摄像头的 PTZ(平移、倾斜、缩放)控制,并希望为用户提供各种与鼠标相关的事件。

使用代码

这段代码本质上会挂接到一个名为 mouseLayer 的 div。你只需要引用 jQuery,一些将 div 定位在某个位置的 CSS,以及以下 JavaScript 库:  

// vlcContainer can be defined from the calling file - this is the ID
// of the VLC player.  if not, the default ID is vlc-player
var vlc;

// cascading events can occur - detection of end events such as single, double and triple left clicks
// for example:  
//      - single left-click without movement does not need to send delta (0, 0)
//      - single left-click with movement needs to send a delta(0, 0)
//      - double left-click - trigger event, but no need to send delta (0, 0) without movement
//      - double left-click with movement (capture X and/or Y); send delta (0, 0)

// send a stopped event if movement with movement detected {t/f}
// if true, stop event sent on button release if movement occurred
// if false, stop event sent on button release
var stopEventWithMovement = {};
stopEventWithMovement["leftSingleClick"] = true;
stopEventWithMovement["leftDoubleClick"] = true;
stopEventWithMovement["leftTripleClick"] = true;
stopEventWithMovement["rightSingleClick"] = true;
stopEventWithMovement["rightDoubleClick"] = true;
stopEventWithMovement["rightTripleClick"] = true;


function getVLC(name) {
    if (window.document[name]) {
        return window.document[name];
    }
    if (navigator.appName.indexOf("Microsoft Internet") == -1) {
        if (document.embeds && document.embeds[name])
            return document.embeds[name];
    }
    else // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
    {
        return document.getElementById(name);
    }

    return null;
}

function registerVideoContainer() {
    // you can define the name ID of the player in JS in the source file
    if (typeof vlcContainer == 'undefined') {
        vlc = getVLC('vlc-player');
    } else {
        vlc = getVLC(vlcContainer);
    }

    try {
        console.log("VLC plugin version: " + vlc.versionInfo());
        // v 2.0.8 Twoflower
    } catch (e) {
        // do nothing
    }

    var options = new Array(":aspect-ratio=4:3", "--rtsp-tcpasdfasdf");
    var id = vlc.playlist.add("rtsp://10.120.7.193/stream1", "LIVE STREAM", options);
    //var id = vlc.playlist.add("http://people.videolan.org/~dionoea/
    //          vlc-plugin-demo/streams/sw_h264.asf", "LIVE STREAM", options);

    vlc.playlist.playItem(id);
}


$(document).ready(function() {

    registerVideoContainer();

    var zoomFactor = 0;
    var relativeStartPosition = function() {
        this.X = 0;
        this.Y = 0;
    };
    var relativePosition = function() {
        this.X = 0;
        this.Y = 0;
    };
    var deltaPosition = function() {
        this.X = 0;
        this.Y = 0;
    };

    var hasClickMovement = false;

    var leftSingleClick = false;
    var leftDoubleClick = false;
    var leftTripleClick = false;

    var rightSingleClick = false;
    var rightDoubleClick = false;
    var rightTripleClick = false;

    var parentOffset;

    var clickCount = 0;
    var longClick = false;

    var isMouseDown = false;

    var clickCounter = {
        increment: function (mouseButton) {
            if (clickCounter._timeout != null)
                clearTimeout(clickCounter._timeout);

            if (clickCounter.mouseButton != mouseButton) {
                clickCounter.count = 0;
                clickCounter.mouseButton = mouseButton;
            }
            clickCounter.count++;
            clickCounter._timeout = setTimeout(clickCounter.reset, 200);
        },
        reset: function () {
            clearTimeout(clickCounter._timeout);
            clickCounter._timeout = null;
            
            if (clickCounter.count > 0) {
                // TODO: Raise event.
                //console.log("raise event");
                //console.log(clickCounter.target);
                $(clickCounter.target).trigger("clickCountEvent", 
                  { count: clickCounter.count, which: clickCounter.mouseButton });
            }
            clickCounter.count = 0;
            clickCounter.mouseButton = null;
        },
        target: null,
        _timeout: null,
        mouseButton: null,
        count: 0

    };

    clickCounter.target = $("#mouseLayer").get(0);
    console.log("test:" + clickCounter.target);


    //
    // hook into the following action end events
    //

    function endCurrentAction() {

        deltaPosition.X = 0;
        deltaPosition.Y = 0;

        if (leftSingleClick & (hasClickMovement && stopEventWithMovement["leftSingleClick"])) {
            // finish single-click with movement
            clickCounter.count = 0;
            $("#deltaDisplay").html("Left Click Stopped: (" + 
               deltaPosition.X + ", " + deltaPosition.Y + ")");
        } else if (leftDoubleClick & (hasClickMovement && stopEventWithMovement["leftDoubleClick"])) {
            // finish double-click with movement
            $("#deltaDisplay").html("Left Double-Click Stopped: (" + 
               deltaPosition.X + ", " + deltaPosition.Y + ")");
        } else if (leftTripleClick & (hasClickMovement && stopEventWithMovement["leftTripleClick"])) {
            // finish triple-click with movement
            clickCounter.count = 0;
            $("#deltaDisplay").html("Left Triple-Click Stopped: (" + 
              deltaPosition.X + ", " + deltaPosition.Y + ")");
        }
        
        if (leftSingleClick & !stopEventWithMovement["leftSingleClick"]) {
            // finish double-click with no movement
            clickCounter.count = 0;
            $("#deltaDisplay").html("Left Click Stopped: (" + 
               deltaPosition.X + ", " + deltaPosition.Y + ")");
        } else if (leftDoubleClick & !stopEventWithMovement["leftDoubleClick"]) {
            // finish double-click with no movement
            clickCounter.count = 0;
            $("#deltaDisplay").html("Left Double-Click Stopped: (" + 
               deltaPosition.X + ", " + deltaPosition.Y + ")");
        } else if (leftTripleClick & !stopEventWithMovement["leftTripleClick"]) {
            // finish triple-click with no movement
            clickCounter.count = 0;
            $("#deltaDisplay").html("Left Triple-Click Stopped: (" + 
               deltaPosition.X + ", " + deltaPosition.Y + ")");
        }
        
        if (rightTripleClick & (hasClickMovement && stopEventWithMovement["rightTripleCLick"])) {
            $("#deltaDisplay").html("Right Triple-Click Stopped: (" + 
               deltaPosition.X + ", " + deltaPosition.Y + ")");
        } else if (rightDoubleClick & (hasClickMovement && stopEventWithMovement["rightDoubleClick"])) {
            $("#deltaDisplay").html("Right Double-Click Stopped: (" + 
               deltaPosition.X + ", " + deltaPosition.Y + ")");
        } else if (rightSingleClick & (hasClickMovement && stopEventWithMovement["rightSingleClick"])) {
            $("#deltaDisplay").html("Right Click Stopped: (" + 
               deltaPosition.X + ", " + deltaPosition.Y + ")");
        }


        leftSingleClick = false;
        leftDoubleClick = false;
        leftTripleClick = false;
        rightSingleClick = false;
        rightDoubleClick = false;
    }

    // disable the browser's context menu for right-clickability
    $(document).bind("contextmenu", function(e) {
        return false;
    });

    $("#mouseLayer").mousemove(function (e) {

        $('body').css('cursor', 'crosshair');

        parentOffset = $(this).parent().offset();
        //offset -> method allows you to retrieve the current
        //   position of an element 'relative' to the document
        relativeStartPosition.X = (e.pageX - parentOffset.left);
        relativeStartPosition.Y = (e.pageY - parentOffset.top);

        deltaPosition.X = relativeStartPosition.X - relativePosition.X;
        deltaPosition.Y = relativePosition.Y - relativeStartPosition.Y;


        if (deltaPosition.X != 0 | deltaPosition.Y != 0) {
            //
            // add hooks here on mouse-move for each button click type, capturing the delta positions
            //
            if (leftSingleClick) {
                hasClickMovement = true;

                $('body').css('cursor', 'move');

                $("#deltaDisplay").html("Delta: (" + 
                     deltaPosition.X + ", " + deltaPosition.Y + ")");
                $("#movement").html(" !!!").css("display", "inline").fadeOut("slow");
            } else if (leftDoubleClick) {
                hasClickMovement = true;

                $("#deltaDisplay").html("Delta: (" + deltaPosition.X + ", " + deltaPosition.Y + ")");
                $("#movement").html(" !!!").css("display", "inline").fadeOut("slow");
            } else if (leftTripleClick) {
                hasClickMovement = true;

                $("#deltaDisplay").html("Delta: (" + deltaPosition.X + ", " + deltaPosition.Y + ")");
                $("#movement").html(" !!!").css("display", "inline").fadeOut("slow");
            } else if (rightSingleClick) {
                hasClickMovement = true;

                $("#deltaDisplay").html("Delta: (" + deltaPosition.X + ", " + deltaPosition.Y + ")");
                $("#movement").html(" !!!").css("display", "inline").fadeOut("slow");
            } else if (rightDoubleClick) {
                hasClickMovement = true;

                $("#deltaDisplay").html("Delta: (" + 
                         deltaPosition.X + ", " + deltaPosition.Y + ")");
                $("#movement").html(" !!!").css("display", "inline").fadeOut("slow");
            } else if (rightTripleClick) {
                hasClickMovement = true;

                $("#deltaDisplay").html("Delta: (" + 
                          deltaPosition.X + ", " + deltaPosition.Y + ")");
                $("#movement").html(" !!!").css(
                         "display", "inline").fadeOut("slow");
            } else {
                relativePosition.X = 0;
                relativePosition.Y = 0;
                //relativeStartPosition.X = 0;
                //relativeStartPosition.Y = 0;
            }
        }

        $("#position").html("<p><strong>X-Position: </strong>" + 
           relativeStartPosition.X + " | <strong>Y-Position: </strong>" + 
           relativeStartPosition.Y + "</p>");

    })
        .bind("clickCountEvent", function (e, data) {
            //console.log("click count: " + data.count);

            switch (data.which) {
                case 1:
                    // left
                    // now if mouse is moved, return new relative positions
                    if (data.count == 1) {              // left single-click
                        if (!leftSingleClick) {
                            relativePosition.X = relativeStartPosition.X;
                            relativePosition.Y = relativeStartPosition.Y;
                        }
                        if (isMouseDown) {
                            leftSingleClick = true;
                            leftDoubleClick = false;
                            leftTripleClick = false;
                            $("#clicked").html("left click");
                        }
                    } else if (data.count == 2) {       // left double-click
                        if (!leftDoubleClick) {
                            relativePosition.X = relativeStartPosition.X;
                            relativePosition.Y = relativeStartPosition.Y;
                        }
                        if (isMouseDown) {
                            leftSingleClick = false;
                            leftDoubleClick = true;
                            leftTripleClick = false;
                            $("#clicked").html("double-left click");
                            $("#zoomFactor").html("Zoom In (click)").css(
                              "display", "inline").fadeOut("slow");
                        }
                    } else if (data.count == 3) {       // left triple-click
                        if (!leftTripleClick) {
                            relativePosition.X = relativeStartPosition.X;
                            relativePosition.Y = relativeStartPosition.Y;
                        }
                        if (isMouseDown) {
                            leftSingleClick = false;
                            leftDoubleClick = false;
                            leftTripleClick = true;
                            $("#clicked").html("triple-left click");
                        }
                    }

                    break;
                case 2:
                    // middle
                    $("#clicked").html("middle click");
                    break;
                case 3:
                    // right
                    if (data.count == 1) {
                        // right single click
                        if (!rightSingleClick) {
                            relativePosition.X = relativeStartPosition.X;
                            relativePosition.Y = relativeStartPosition.Y;
                        }
                        if (isMouseDown) {
                            rightSingleClick = true;
                            rightDoubleClick = false;
                            rightTripleClick = false;
                            $("#clicked").html("right click");
                        }
                    } else if (data.count == 2) {
                        // right double click
                        if (!rightDoubleClick) {
                            relativePosition.X = relativeStartPosition.X;
                            relativePosition.Y = relativeStartPosition.Y;
                        }
                        if (isMouseDown) {
                            rightSingleClick = false;
                            rightDoubleClick = true;
                            rightTripleClick = false;
                            $("#clicked").html("double-right click");
                            $("#zoomFactor").html("Zoom Out (click)").css(
                               "display", "inline").fadeOut("slow");
                        }
                    } else if (data.count == 3) {
                        // right triple click
                        $("#clicked").html("triple-right click");
                        if (!rightDoubleClick) {
                            relativePosition.X = relativeStartPosition.X;
                            relativePosition.Y = relativeStartPosition.Y;
                        }
                        if (isMouseDown) {
                            rightSingleClick = false;
                            rightDoubleClick = false;
                            rightDoubleClick = true;
                            $("#clicked").html("triple-left click");
                        }
                    }
                    break;
                default:
                    // error
                    $("#clicked").html("unsupported mouse: " + e.which);
            }


        })
    .mousedown(function (e) {
        isMouseDown = true;
        clickCounter.increment(e.which);
    })
    .mouseout(function () {
        clickCounter.count = 0;

        isMouseDown = false;

        $("#position").html("<p><strong>X-Position: </strong>" + 
            relativeStartPosition.X + " | <strong>Y-Position: </strong>" + 
            relativeStartPosition.Y + "</p>");
        $('body').css('cursor', 'default');

        if ((deltaPosition.X != 0 && deltaPosition.Y != 0) | 
                 (!isNaN(deltaPosition.X) && !isNaN(deltaPosition.Y))) {
            //console.log(deltaPosition.X + ", " + deltaPosition.Y);
            endCurrentAction();
        }
    })
    .mouseup(function (event) {
        isMouseDown = false;
        
        $("#clicked").html("");
        $("#deltaDisplay").html("");
        $('body').css('cursor', 'crosshair');
        endCurrentAction();
  
        hasClickMovement = false;
        
        //console.log("Mouse up dPos: " + (deltaPosition.X + ", " + deltaPosition.Y));

    });

    $('#mouseLayer').bind('mousewheel', function (event, delta) {
        if (event.originalEvent.wheelDelta > 0) {
            $("#zoomFactor").html("Zoom In").css(
                   "display", "inline").fadeOut("slow");
        } else {
            $("#zoomFactor").html("Zoom Out").css(
                     "display", "inline").fadeOut("slow");
        }

        return false;
    });
    
});

代码解释 

#mouseLayer 中,我们 .bind() clickCountEvent 函数,该函数通过 switch() 语句响应适当的 data.count。 

单击次数由 clickCounter 管理,单击次数的输出由单击之间的延迟决定,在本例中为 200 毫秒: 

clickCounter._timeout = setTimeout(clickCounter.reset, 200); 

在每个 switch 分支中,我们开始跟踪按钮按下期间的 delta X/Y。 通过这些值(可以想象成点击时创建的新向量),你可以为你要控制的任何内容设置一个加速因子。 

你可能还需要为你的设备发送一个“停止”事件。这是通过释放按钮点击来实现的。

你可以在文件头定义的 stopEventWithMovement[whichButtonClickType]={bool} 数组中选择是否引发停止事件(因为如果鼠标没有移动,你可能不需要它)。

样式 

以下是我设置激活 DIV 的 CSS 的方式: 

/* positioning is relative to the container */
#mouseLayer{
    position: absolute;
    top:10px;
    left:10px;
    height: calc(90% - 20px);
    width: calc(90% - 10px);
	/*height: auto;*/
    /*min-height:480px;*/
	margin:0px auto;
    overflow-y: auto;

    z-index:1000;
	
	text-align:left;
	padding:15px;
	border:1px dashed #333;
	/*background-color:#0000ee;*/
    background-color:rgba(255,0,0,0.05);

	padding-top: 30px;
	overflow: hidden;
}

关注点

要查看事件激活时触发的诊断代码,请参阅 http://www.whatsinyourlunch.com/capturing-client-side-mouse-events-with-javascript-jquery/。 在这里,我将更详细地介绍如何跟踪某些条件 mouseUp 事件 以及如何设置参数。 

你可以通过简单地在 switch 语句中添加新的可触发值来设置 N 次单击的事件。因此,你可以触发 10 次左键单击、30 次右键单击等事件。 

历史

没有重大历史记录。

© . All rights reserved.