韶关网页设计:浏览器输入事件——我们能比点击更好吗?

2019.08.12 mf_web

170

响应用户输入可以说是我们作为界面开发人员所做的核心。为了构建响应式Web产品,了解触摸,鼠标,指针和键盘操作以及浏览器如何协同工作是关键。您可能在移动浏览器中经历了300毫秒的延迟,或者在触摸移动与滚动之间进行了摔跤。韶关网页设计

在本文中,我们将介绍事件级联,并使用此知识实现一个tap事件的演示,该事件支持许多输入方法,而不会破坏Opera Mini等代理浏览器。

概观

今天使用三种主要输入方法与网络交互:数字光标(鼠标),触觉(直接触摸或手写笔)和键盘。我们可以通过触摸事件,鼠标事件,指针事件和键盘事件在JavaScript中访问这些内容。在本文中,我们主要关注基于触摸和鼠标的交互,尽管某些事件具有基于键盘的标准交互,例如click和submit事件。

您很可能已经为触摸和鼠标事件实现了事件处理程序。当推荐的方法类似于此时,在我们不太遥远的传球中有一段时间:

/** DO NOT EVER DO THIS! */$('a', ('ontouchstart' in window) ? 'touchend' : 'click', handler);
复制

微软一直致力于通过“指针事件”规范创建一个面向未来的更好的事件模型。指针事件是一种抽象输入机制,现在是W3C推荐。指针事件使用户代理(UA)具有在一个事件系统下容纳众多输入机制的灵活性。鼠标,触控和手写笔都是今天很容易想到的例子,虽然扩展到Myo或Ring的实现是可以想象的。虽然Web开发人员似乎对此感到非常兴奋,但并非所有浏览器工程师都有同感。也就是说,Apple和Google已决定此时不实施指针事件。

谷歌的决定不一定是最终决定,但在指针事件上没有积极的工作。我们通过polyfill和替代解决方案输入和使用指针事件将成为方程式的一部分,最终可能会以另一种方式缩小规模。苹果公司在2012年发表了针对指针事件的声明,我不知道Safari工程师的任何公众回应。

事件级联

当用户点击移动设备上的元素时,浏览器会触发大量事件。这个动作通常会触发一系列事件,如以下情况:touchstart→交通touchend→交通mouseover→交通mousemove→交通mousedown→交通mouseup→交通click。

这是由于与网络的向后兼容性。指针事件采取另一种方法,烧成兼容性事件直列:mousemove→交通pointerover→交通mouseover→交通pointerdown→交通mousedown→交通gotpointercapture→交通pointerup→交通mouseup→交通lostpointercapture→交通pointerout→交通mouseout→交通focus→交通click。

事件规范允许UA在兼容性事件的实现方面有所不同。Patrick Lauke和Peter-Paul Koch在这个主题上保留了大量的参考资料,这些资料与本文底部的资源部分相关联。

以下图形显示了以下操作的事件级联:

  1. 初始点击一个元素,

  2. 第二次敲击一个元素,

  3. 敲掉元素。

请注意:此事件堆栈故意忽略适合此堆栈的位置focus和blur事件。

iOS设备上的事件级联,用于点击元素两次然后点击
iOS设备上的事件级联,用于点击元素两次然后点击。(图片来源:Stephen Davis)(查看大图)
该事件在大多数Android 4.4设备上级联,用于点击元素两次然后点击
该事件在大多数Android 4.4设备上级联,用于点击元素两次然后点击。(图片来源:Stephen Davis)(查看大图)
IE 11上的事件级联(在实现兼容性触摸事件之前),用于两次点击元素然后再点击。
Internet Explorer 11上的事件级联(在实现兼容性触摸事件之前),用于两次点击元素然后点击。(图片来源:Stephen Davis)(查看大图)

应用事件级联

由于浏览器工程师的努力,今天为桌面网站构建的大多数网站“正常工作”。尽管级联看起来很粗糙,但像我们以前一样建立鼠标事件的保守方法通常会起作用。

当然,有一个问题。臭名昭著的300毫秒的延迟是最有名的,但滚动,之间的相互作用touchmove和pointermove活动,以及浏览器画是其他问题。如果出现以下情况,可以轻松避免300毫秒的延迟:

  • 我们仅针对Android和桌面的现代Chrome进行优化,使用启发式方法<meta name="viewport" content="width=device-width">来禁用延迟;

  • 我们只针对iOS进行优化,并且用户进行了明确的按键,但不是快速点击而不是长按 - 只是一个好的,正常的,清晰的元素按下(哦,它还取决于它是在UIWebView还是WKWebView - 阅读FastClick关于该主题的问题,以获得良好的呐喊。

如果我们的目标是构建与用户体验和浏览器中的本机平台竞争的Web产品,那么我们需要减少交互响应延迟。为实现这一目标,我们需要在原始事件(down,move和up)的基础上构建我们自己的复合事件(click,double-click)。当然,我们仍然需要为本机事件包含后备处理程序,以获得广泛的支持和可访问性。

这样做不需要少量的代码或知识。为了避免浏览器延迟300毫秒(或任何长度),我们需要自己处理完整的交互生命周期。对于给定的{type}down事件,我们需要绑定完成该操作所需的所有事件。当交互完成后,我们将需要通过解除除了起始事件之外的所有事件来清理自己。

您,网站开发人员,是唯一知道页面是否应该缩放或是否必须等待的另一个双击事件的人。如果 - 并且仅当 - 您需要延迟回调,如果您允许延迟执行预期的操作。

在以下链接中,您将找到一个小的,无依赖关系的点击演示,以说明创建多输入,低延迟点击事件所需的工作量。Polymer-gestures是一个生产就绪的tap和其他事件的实现。尽管名称如此,但它不以任何方式与Polymer库相关联,并且可以轻松地单独使用。

要清楚,从头开始实现这个是一个坏主意。以下仅用于教育目的,不应用于生产。存在生产就绪的解决方案,例如FastClick,聚合物手势和Hammer.js。

  • 演示:点击事件

  • 代码: taps.js

重要的比特

绑定您的初始事件处理程序就是一切开始的地方。以下模式被认为是处理多设备输入的防弹方式。

/**
 * If there are pointer events, let the platform handle the input 
 * mechanism abstraction. If not, then it’s on you to handle 
 * between mouse and touch events.
 */if (hasPointer) {
  tappable.addEventListener(POINTER_DOWN, tapStart, false);
  clickable.addEventListener(POINTER_DOWN, clickStart, false);}else {
  tappable.addEventListener('mousedown', tapStart, false);
  clickable.addEventListener('mousedown', clickStart, false);
  if (hasTouch) {
    tappable.addEventListener('touchstart', tapStart, false);
    clickable.addEventListener('touchstart', clickStart, false);
  }}clickable.addEventListener('click', clickEnd, false);
复制

绑定触摸事件处理程序可能会影响渲染性能,即使它们不执行任何操作。为了减少这种影响,通常建议在起始事件的处理程序中绑定跟踪事件。不要忘记自己清理并在动作完成的处理程序中解除跟踪事件的绑定。

/**
 * On tapStart we want to bind our move and end events to detect 
 * whether this is a “tap” action.
 * @param {Event} event the browser event object
 */function tapStart(event) {
  // bind tracking events. “bindEventsFor” is a helper that automatically 
  // binds the appropriate pointer, touch or mouse events based on our 
  // current event type. Additionally, it saves the event target to give 
  // us similar behavior to pointer events’ “setPointerCapture” method.
  bindEventsFor(event.type, event.target);
  if (typeof event.setPointerCapture === 'function') {
    event.currentTarget.setPointerCapture(event.pointerId);
  }
  // prevent the cascade
  event.preventDefault();
  // start our profiler to track time between events
  set(event, 'tapStart', Date.now());}/**
 * tapEnd. Our work here is done. Let’s clean up our tracking events.
 * @param {Element} target the html element
 * @param {Event} event the browser event object
 */function tapEnd(target, event) {
  unbindEventsFor(event.type, target);
  var _id = idFor(event);
  log('Tap', diff(get(_id, 'tapStart'), Date.now()));
  setTimeout(function() {
    delete events[_id];
  });}
复制

其余代码应该是不言自明的。事实上,这是很多簿记。实现自定义手势需要您与浏览器事件系统密切合作。为了避免痛苦和心痛,请不要在整个代码库中单独执行此操作; 相反,构建或使用强大的抽象,如Hammer.js,指针事件 jQuery polyfill或聚合物手势。

结论

过去非常清楚的某些事件现在充满了歧义。该click事件过去只是意味着一件事,但是触摸屏通过需要辨别动作是双击,滚动,事件还是其他一些操作系统级别的手势来使其复杂化。

好消息是,我们现在更了解事件级联以及用户操作和浏览器响应之间的相互作用。通过了解工作中的原语,我们能够在我们的项目,用户和Web的未来中做出更好的决策。

韶关网页设计在构建多设备网站时遇到了哪些意想不到的问题?您采取了哪些方法来解决我们在网络上的众多交互模型?


最新案例

寒枫总监

来电咨询

400-6065-301

微信咨询

寒枫总监

TOP