为移动Web应用建立快速响应按钮

英文原文出自 Google Deveploers《Creating Fast Buttons for Mobile Web Applications》,由XiaoYi_HD翻译,并首发于 EsoftMobile.com。如需转载,请注明译者及出处信息。html

背景

在 Google,咱们不断地突破移动 Web 应用可以达到的效果,相似于 HTML5 这类技术让咱们对原生应用和 Web 应用的界线开始变得模糊。为了这个目标,咱们开发了一种新技术让纯 HTML 按钮可以有更快的响应速度。这以前,咱们可能只是为按钮或者其余能够点击的元素增长点击处理,如:git

 

<button onclick='signUp()'>Sign Up!</button>

使用这种方法存在一个问题就是,移动浏览器会在你点击按钮后 300ms 才触发事件,缘由是浏览器须要区分你是不是要执行双击。可是对于大多数按钮,咱们并不须要它处理双击事件,因此 300ms 的延时时间对于只是想执行点击事件的用户来讲太长了。咱们最先开发这种技术是在Google Voice mobile web app中,咱们但愿可以更加迅速的调用拨号事件。github

 

处理触摸事件

该技术涉及一点 JavaScript 的东西来让按钮响应触摸(Touch)事件而不是点击(Click)事件。触摸事件响应不会有延时因此感觉会比点击事件快不少,可是咱们也须要考虑如下几个问题:web

  1. 若是用户是点击屏幕上其余的元素而触发了按钮的触摸事件,这种状况咱们不该该去执行按钮的事件。
  2. 若是用户按下按钮而后拖到屏幕其余位置而触发了触摸事件,咱们也不该该执行按钮的事件。
  3. 咱们但愿按钮在按下的时间可以高亮来表示点击状态。

咱们可以经过检测 touchstart 和 touchmove 事件来解决前两个问题,只须要考虑一个一开始在按钮上就是 touchstart 状态的触摸事件,而若是 touchstart 后存在了一个 touchmove,那咱们就不该该处理 touchend 事件。浏览器

咱们能够经过同时给按钮添加 onclick 处理来解决第三个问题,这样浏览器就会把它当成按钮并在点击时出现高亮。咱们 touchend 处理也能保证按钮仍然很快响应,同时添加 onclick 能够在不支持触摸事件的浏览器上作为比较可靠的备用方案。app

破坏讨厌的点击

在添加触摸事件的同时添加 onclick 事件又会带来另外一个讨厌的问题,当你点击按钮时,点击 (click) 事件仍然会在 300ms 后执行,咱们能够经过在 touchstart 事件里调用 preventDefault 来解决。在 touchstart 中调用 preventDefault 方法会会致使点击和滑动失效,但咱们又想用户可以滑动视图即便一开始是点在按钮上,因此咱们仍不能接受这种解决方案。接来下咱们想出了一个被咱们叫作点击破坏者(Click buster)的方案,咱们给 body 添加一个点击事件监听(listener),当监听事件被触发,咱们会区分点击是否由咱们已经处理的 tap 事件致使的,若是这样,咱们才调用 preventDefault 和 stopPropagation。iphone

Fast Button Code

下面咱们会提供一些咱们实现这个想法的代码。测试

经过标签和事件建立一个 FastButtonui

 

google.ui.FastButton = function(element, handler) {
	this.element = element;
	this.handler = handler;
	
	element.addEventListener('touchstart', this, false);
	element.addEventListener('click', this, false);
};

google.ui.FastButton.prototype.handleEvent = function(event) {
	switch(event.type) {
		case 'touchstart': this.onTouchStart(event); break;
		case 'touchmove': this.onTouchMove(event); break;
		case 'touchend': this.onTouchEnd(event); break;
		case 'click': this.onClick(event); break;
	}
};

保存 touchstart 坐标,并开始监听 touchmove 和 touchend 事件,调用 stopPropagation 来保证其余操做不会触发点击事件。this

 

 

google.ui.FastButton.prototype.onTouchStart = function(event) {
	event.stopPropagation();
	
	this.element.addEventListener('touchend', this, false);
	document.body.element.addEventListener('touchmove', this, false);
	
	this.startX = event.touches[0].clientX;
	this.startY = event.touches[0].clientY;
};

当 touchmove 事件触发时,检查用户是否拖动超过 10px。

 

 

google.ui.FastButton.prototype.onTouchMove = function(event) {
	if (Math.abs(event.touches[0].clientX - this.startX) > 10 ||
		Math.abs(event.touches[0].clientY - this.startY) > 10) {
		this.reset();	
	}
};

执行真正的点击事件并在 touchend 事件时避免讨厌的 click。

 

 

google.ui.FastButton.prototype.onClick = function(event) {
	event.stopPropagation();
	this.reset();
	this.handler(event);
	
	if (event.type == 'touchend') {
		google.clickbuster.preventGhostClick(this.startX, this.startY);
	}
};

google.ui.FastButton.prototype.reset = function() {
	this.element.removeEventListener('touchend', this, false);
	document.body.removeEventListener('touchmove', this, false);
}

调用 preventGhostClick 来破坏在接下来 2.5s 内 x, 移动距离在 25px 内的点击事件。

 

 

google.clickbuster.preventGhostClick = function(x, y) {
	google.clickbuster.coordinates.push(x ,y);
	window.setTimeout(google.clickbuster.pop, 2500);
};

google.clickbuster.pop = function() {
	google.clickbuster.coordinates.splice(0, 2);
};

若是咱们在给定的半径和时间内捕获到了点击事件,调用 stopPropagation 和 preventDefault。

 

 

google.clickbuster.onClick = function(event) {
	for (var i = 0; i < google.clickbuster.coordinates.length; i += 2) {
		var x = google.clickbuster.coordinates[i];
		var y = google.clickbuster.coordinates[i + 1];
		if (Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) {
		event.stopPropagation();
		event.preventDefault();
		}
	}
};

document.addEventListener('click', google.clickbuster.onClick, true);
google.clickbuster.coordinates = [];

 

总结

到这里你应该可以建立快速响应的按钮了,花一点心思,你可让它们看起来更像你所面向平台的原生按钮。如今已经有一些 JavaScript 库也提供了这种问题的解决方案,可是到目前为止咱们没有发现有提供可靠备选方案和讨厌的点击问题。咱们但愿浏览器开发者可以在可以解决在不能缩放的页面上快速响应的问题,事实上咱们已经在 Gingerbread 的浏览器上实现了。

测试代码FastButtonDemo已上传 github。

Posted by XiaoYi_HD - 6月 27 2013
如需转载,请注明: 本文来自 Esoft Mobile

相关文章
相关标签/搜索