在没有 jQuery mobile 的移动设备上使用 mousedown 事件?

Posted

技术标签:

【中文标题】在没有 jQuery mobile 的移动设备上使用 mousedown 事件?【英文标题】:Using mousedown event on mobile without jQuery mobile? 【发布时间】:2012-06-24 01:18:15 【问题描述】:

我已经构建了一个 web 应用程序,为了稍微完善一下,我想添加 mousedown 和 mouseup 处理程序来交换图像(在这种情况下,使按钮看起来像是被按下了)。

我的代码是这样的:

window.onload = function() 
    //preload mouse down image here via Image()
    $("#button_img").mousedown(function()$("#button_img").attr("src","button_on.png"););
    $("#button_img").mouseup(function()$("#button_img").attr("src","button_off.png"));

这在桌面上运行良好,但在移动设备上(在 ios Safari 中测试),mousedown 和 mouseup 事件同时发生,因此实际上什么也没发生。

我尝试在 jQueryMobile 中使用 vmousedown 和 vmouseup 事件,但是这段代码:

//include jquerymobile.js and jquerymobile.css 
window.onload = function() 
    //preload mouse down image here via Image()
    $("#button_img").vmousedown(function()$("#button_img").attr("src","button_on.png"););
    $("#button_img").vmouseup(function()$("#button_img").attr("src","button_off.png"));

只是给了我 vmousedown 和 vmouseup 不存在的错误。此外,jQueryMobile 会覆盖我已经为页面编写的 CSS。

那么有没有办法让 vmousedown 和 vmouseup 工作,并且在没有 jQuery Mobile 的 CSS 的情况下这样做?

【问题讨论】:

嘿伙计!您在下面得到了答案,这一切都很好。但是请注意:在按钮上使用图像并不是最好的用户体验,请尝试仅使用 css。您可以在 getbootstrap.com/components 和许多其他框架中找到一些不错的按钮样式,甚至可以创建自己的样式。试试吧!你会喜欢的 @Guilherme:您知道,在按钮上使用图像是有正当理由的。就我而言,我正在使用 SVG 模拟一个物理摇杆开关,这是仅使用 CSS 无法做到的。但我也没有直接操作按钮样式。我所做的只是添加和删除一个类名。 Nice :D 图像还不错,只是并不总是最好的选择。在这种情况下,即使可以对它进行 css,我也会使用图像。 【参考方案1】:

您正在寻找touchstarttouchend。它们是vmousedownvmouseup 试图模仿的事件。

这是一个例子:

window.onload = function() 
    //preload mouse down image here via Image()
    $("#button_img").bind('touchstart', function()
        $("#button_img").attr("src","button_on.png");
    ).bind('touchend', function()
        $("#button_img").attr("src","button_off.png");
    );

这在任何支持触摸事件的设备上都可以在没有任何框架的情况下工作。你可以使用Modernizr 之类的东西来做这个测试,如果设备不支持触摸事件,绑定到常规的桌面事件。

当您使用touchstart/touchend/touchmove 时,您会得到一些有趣的信息,例如一次发生了多少次触摸,因此您可以检测用户是否在滚动或尝试缩放。

更新

由于事件处理程序中的 event 对象对于触摸事件和鼠标事件是不同的,如果你想知道事件的坐标,你可以这样做(下面的例子假设 Modernizr 已经加载) :

//determine which events to use
var startEventType = 'mousedown',
    endEventType   = 'mouseup';

if (Modernizr.touch === true) 
    startEventType = 'touchstart';
    endEventType   = 'touchend';


//bind to determined event(s)
$("#button_img").bind(startEventType, function(event) 

    //determine where to look for pageX by the event type
    var pageX = (startEventType === 'mousedown')
                ? event.pageX
                : event.originalEvent.touches[0].pageX;

    ...
)...

更新

我正在查看这个,您似乎不需要在绑定事件处理程序之前检测事件类型:

//bind to determined event(s)
$("#button_img").bind('mousedown touchstart', function(event) 

    //determine where to look for pageX by the event type
    var pageX = (event.type.toLowerCase() === 'mousedown')
                ? event.pageX
                : event.originalEvent.touches[0].pageX;

    ...
)...

如果您担心快速连续接收这两个事件,您可以使用超时来限制事件处理程序:

//create timer
var timer = null;

//bind to determined event(s)
$("#button_img").bind('mousedown touchstart', function(event) 

    //clear timer
    clearTimeout(timer);

    //set timer
    timer = setTimeout(function () 

        //determine where to look for pageX by the event type
        var pageX = (event.type.toLowerCase() === 'mousedown')
                    ? event.pageX
                    : event.originalEvent.touches[0].pageX;

        ...

    , 50);
)...

注意:您可以使用开发人员工具快速连续地强制 mousedowntouchstart 事件,但我不确定这里的真实用例。

【讨论】:

虽然这似乎满足了 OP 的特定用例,但这个答案并没有像提出的那样回答问题,而且不准确。 Vmousedown 和 vmouseup 不只是“试图模仿” touchstart 和 touchend。它们还抽象出触摸事件和鼠标事件之间的所有差异,以便您可以像使用 mouseup 和 mousedown 一样使用 vmousedown 和 vmouseup。如果使用 touchstart 和 touchend,一般情况下,可能需要更改大量内容,并且还需要为这两种事件复制代码。 所以,这个问题仍然没有答案:如何在不使用整个 jquerymobile 框架的情况下利用 vmouseup 和 vmousedown。 非常感谢。与此同时,我发现可以在jquerymobile.com/download-builder 下载自定义构建的 jquerymobile,并且只包含您需要的模块,在这种情况下是虚拟鼠标,顺便说一下,这似乎是相当多的代码(但它也包括 vmousemove)。不过还是要试试看 @matteo 这是 jQuery Mobile 开发人员制作的一个不错的工具。看起来只从 jQuery Mobile 下载 vmouse 事件的文件大小与使用 Modernizr 的文件大小大致相同。 是的,但除了文件大小之外,我想它们几乎没有共同点。 Jquery mobile 的 vmouse 模块似乎处理了很多事情,以使虚拟鼠标事件尽可能完整和透明地替代鼠标事件,我认为现代化器不会这样做(除了检测功能支持);现代化器也很可能做了很多不相关的事情,显然 jquerymobile 的 vmouse 没有。顺便说一句,我刚刚尝试过,它可以工作。【参考方案2】:

您是否考虑过使用 CSS 来设置按钮样式? :active 状态将在用户单击/触摸元素时触发。这是一个例子:

/* Default state */
#button_img 
    background-image: url('button_off.png');


/* Clicked/touched state */
#button_img:active  
    background-image: url('button_on.png');

CSS 的性能会更高,您还可以更好地分离关注点(显示与逻辑等)。

JSBin:http://jsbin.com/beyin/1/

【讨论】:

我不知道为什么这个答案被否决了,确实是,我同意这不是初学者所要求的,但特别考虑到请求本身是关于图像交换的(以及公平地说,从他似乎不知道几个概念的那种要求来看)我完全支持这个答案。此外,我想补充一点,JS 在完全有权使用 CSS 的任务中被滥用。这种行为应该被彻底根除,我鼓励人们使用 CSS 进行渲染(这也更快),让 JS 去做它应该做的事情:成为一个控制器。 我对答案投了反对票,因为它与回答问题无关,这是关于 vmouse 事件的一个非常具体的问题,这个答案建议甚至不使用事件。这可能是问题中提供的特定示例的解决方案,但它没有解决问题,也不适用于需要事件的任何用例。这种建议的正确位置是对问题的评论。如果这是评论,我什至会赞成。 OP显示多少知识无关紧要;答案适用于所有人,而不仅仅是 OP。 @matteo OP 在第一句话中说“为了稍微润色,我想...换掉图像(在这种情况下,使按钮看起来像是被按下了)。 "他们正在询问如何做到这一点,但已经开始使用 jQuery 沿着某个路径前进。这条路径不是“使按钮看起来像是被按下”的理想方式。 OP 可能仍然使用他们的 jQuery 解决方案,但 CSS 是执行此操作的“正确”方式。这个答案不属于评论,即使它最终不是被接受的答案。 问题的标题是“在没有 jQuery mobile 的情况下在移动设备上使用 mousedown 事件?”。交换图像用例可以被认为是应用程序的一个简单示例。如果问题的主体似乎与其标题不一致,则可以在评论中要求 OP 进行澄清。如果问题证明了想要做问题所要求的错误动机,那么评论是建议恕我直言的地方。您可以随意将其发布为答案,但我认为它对这个问题的回答不好,这就是我投反对票的原因(顺便说一句,我只是因为被问到而解释的)。 这与它是否被接受无关(实际上我也不认为接受的一个是一个很好的答案,但它确实解决了这个问题,我只是赞成它在对其进行编辑以包含更多细节之后,因为我感谢它提供的帮助)。不,我不会对每个不是确切解决方案的答案都投反对票,我只会在我认为这是一个糟糕的答案或属于评论而不是答案的情况下才会这样做。我特别不喜欢那种“你要求的不是你应该做的”的答案。当然这只是我的意见和投票。【参考方案3】:

有一种方法可以获得jQueryMobile 的vmouseupvmousedownvmousemovevclick 等功能,而无需获得jquerymobile 的所有其余部分(尤其是副作用)(即增强、额外css等)

转至http://jquerymobile.com/download-builder/(用于下载自定义构建的 jquerymobile 的工具,其中仅包含您需要的组件) 仅选择“虚拟鼠标 (vmouse) 绑定” 下载吧。

下载将仅包含一个 .js 文件(最小化和未压缩版本)。没有 CSS。

在纯 jquery 之后将此脚本链接到 html 的头部,并像这样使用它:

<head>
  <script src="http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
  <script src="whatever/path/jquery.mobile.custom.min.js"></script>
  <script>
    $(function() // or replace this with window.onload for that matter
      // Your code here, e.g.
      $("#button_img").on("vmousedown", function()  
        /*whatever*/
      );
      // CAUTION: this won't work (see note below):
      // $("#button_img").vmousedown(function()/*whatever*/); // WON'T WORK
    );
  </script>
</head>

注意.vmousedown().vmouseup()等方法不起作用。您必须将事件侦听器与.on("vmousedown", ...) 绑定。 不知道为什么:我猜这是因为创建与事件同名的快捷方法的 jquerymobile 部分位于其他模块中。也许可以找出它是哪个模块并将其包含在下载中,但我认为它会迫使您包含其他不需要的依赖项。

【讨论】:

vmouse 事件是自定义事件而不是方法,因此您需要绑定 .on() unbind .off() 它们。 太棒了,效果很好,不会强迫我使用 jQuery UI 或完整的 jQuery Mobile 库。 完美,正是我所追求的,我不需要 Jquery 移动 CSS 或其他东西,而且它显示的加载消息正在加重。非常感谢 =)【参考方案4】:

对触摸设备使用 touchstart 或 touchend。

大多数时候你想捕捉 touchstart 和 mousedown。您需要确保处理程序只触发一次。最简单的方法是同时捕获它们并调用 e.preventDefault()。

$("#button_img").on('touchstart mousedown', function(e) 
  //your code...

  e.preventDefault(); //prevents further events from being dispatched

来源:developer.mozilla.org:

如果浏览器因为单个用户输入而同时触发触摸和鼠标事件,则浏览器必须在任何鼠标事件之前触发 touchstart。因此,如果应用程序不希望在特定的触摸目标元素上触发鼠标事件,则该元素的触摸事件处理程序应调用 preventDefault() 并且不会调度其他鼠标事件。

【讨论】:

以上是关于在没有 jQuery mobile 的移动设备上使用 mousedown 事件?的主要内容,如果未能解决你的问题,请参考以下文章

适用于桌面和移动设备的 jQuery Mobile

Jquery 判断是否 移动设备 浏览

JQuery Mobile 1.4 如何在移动设备上禁用悬停效果

Jquery mobile getJSON 适用于浏览器但不适用于移动设备

jquery mobile - 移动设备上的keyup keydown

更改设备方向上的图像 jquery-mobile