背景

在谷歌,我们不断地推测手机网页应用的可能性。像HTML5这样的技术使我们网页版的应用以及运行在手机设备上的原生应用。而这些技术的成就之一就是我们开发了一种新的创建按钮的方法,使按钮的响应时间远远快于一般的HTML按钮。在此之前的按钮或者其他响应事件,我们可能会设计一个点击事件。例如:

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

这种方法的问题是,当你开始点击按钮开启点击事件时,浏览器会停留大约300毫秒的时间。这是因为浏览器在等待,看你是否双击按钮。对于大多数的按钮,我们在开发的时候就知道不会执行双击事件,所以点击后等待的这段时间是在浪费用户的时间。我们在Google Voice手机网页应用上第一次使用这种技术,目的是想让用户拨号时有更快的相应速度。

处理触摸事件

这个技术涉及到一点javascript,允许按钮对touchEnd事件响应而不是click事件。touchEnd事件的触发是没有延迟的,所以能够明显的比click事件要快,但是仍有一些问题值得考虑:

1.如果用户轻触了屏幕的某个地方然后引起了一个按钮的touchEnd事件,而我们不应该由此触发一个click事件。

2.如果用户按下了按钮,然后在屏幕上拖动了一段距离,然后引起按钮的touchEnd事件,此时我们也不应该触发click事件。

3.我们希望当用户按下按钮时,能够给这个按钮一个按下的状态,从而使得其突出显示。

我们能够通过监听touchStart和touchMove事件解决前两个问题。如果在按钮上之前有touchStart事件,那么我们才会考虑在按钮上的touchEnd事件。同样,如果有一个touchMove事件且同touchStart的位置相比移动超过了某个阈值,那么我们就不应该把这个touchEnd事件当做click事件来处理。

我们也可以通过给按钮添加一个onclick处理函数来解决第三个问题。那么做会恰好让浏览器于把他当做按钮,而我们的touchEnd处理函数仍能够确保这个按钮响应很快。同样,一个onclick处理函数的存在,也能让那些不支持touch事件的浏览器优雅降级。

消除幽灵点击

重新添加onclick处理函数给按钮,会引发最后一个令人讨厌的问题。但你轻触按钮时,一个click事件仍然会在300ms后被触发。现在这个click处理函数就有被运行两次的危险。这个可以通过在touchStart事件中调用preventDefault 很容易被解决。在touchStart事件中调用preventDefault方法将会阻止当前的轻触所引发的的click和scrolling。我们希望用户可以滚动页面,即使他们从按钮的位置开始滚动,所以我们不认为这是一个可接受的解决方案。我们想出的能解决幽灵点击的方法叫做click buster(点击破坏者)。我们所做的只是在页面body中添加一个click的监听器,在捕获阶段监听。当我们的监听器被触发,我们就会尝试判定这个click事件是不是我们已经当做tap事件来处理的结果。如果是的话,我们就可以调用preventDefault和stopPropagation来阻止他。

(function(){/** * From: http://code.this.com/mobile/articles/fast_buttons.html* Also see: http://stackoverflow.com/questions/6300136/trying-to-implement-googles-fast-button*//** For IE8 and earlier compatibility: https://developer.mozilla.org/en/DOM/element.addEventListener */function addListener(el, type, listener, useCapture){if (el.addEventListener) {el.addEventListener(type, listener, useCapture);return {destroy: function(){el.removeEventListener(type, listener, useCapture);}};}else {var handler = function(e){listener.handleEvent(window.event, listener);}el.attachEvent('on' + type, handler);return {destroy: function(){el.detachEvent('on' + type, handler);}};}}var isTouch = "ontouchstart" in window;/* 构建fastbutton与元素的引用并单击处理程序. */this.FastButton = function(element, handler, useCapture){// 收集功能调用清除事件 this.events = [];this.touchEvents = [];this.element = element;this.handler = handler;this.useCapture = useCapture;if (isTouch) this.events.push(addListener(element, 'touchstart', this, this.useCapture));this.events.push(addListener(element, 'click', this, this.useCapture));};/* 移除事件处理时,不再需要这个按钮 */this.FastButton.prototype.destroy = function(){for (i = this.events.length - 1; i >= 0; i -= 1) this.events[i].destroy();this.events = this.touchEvents = this.element = this.handler = this.fastButton = null;};/* 作为一个事件调度 */this.FastButton.prototype.handleEvent = function(event){switch (event.type) {case 'touchstart':this.onTouchStart(event);break;case 'touchmove':this.onTouchMove(event);break;case 'touchend':this.onClick(event);break;case 'click':this.onClick(event);break;}};/* 保留对touchStart位置的引用,然后开始监听touchMove和touchEnd事件。调用stopPropagation来保证另一个动作不会再次处理同样的点击事件. */this.FastButton.prototype.onTouchStart = function(event){event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);this.touchEvents.push(addListener(this.element, 'touchend', this, this.useCapture));this.touchEvents.push(addListener(document.body, 'touchmove', this, this.useCapture));this.startX = event.touches[0].clientX;this.startY = event.touches[0].clientY;};/* 当一个touchMove事件被触发,检查用户是否推动超过10px这个阈值. */this.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(); //如果ture,然后取消触摸事件
                    }};/*触发一个实际的click处理函数,如果有touchEnd事件,就阻止幽灵点击事件. */this.FastButton.prototype.onClick = function(event){event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);this.reset();// Use .call to call the method so that we have the correct "this": https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/callvar result = this.handler.call(this.element, event);if (event.type == 'touchend') clickbuster.preventGhostClick(this.startX, this.startY);return result;};this.FastButton.prototype.reset = function(){for (i = this.touchEvents.length - 1; i >= 0; i -= 1) this.touchEvents[i].destroy();this.touchEvents = [];};this.clickbuster = function(){}/* 调用preventGhostClick来消除掉所有的在2.5s内且在不超过保留的x,y坐标周围25px的点击事件 */this.clickbuster.preventGhostClick = function(x, y){clickbuster.coordinates.push(x, y);window.setTimeout(clickbuster.pop, 2500);};this.clickbuster.pop = function(){clickbuster.coordinates.splice(0, 2);};/*如果我们 在给定的范围和时间阈值里捕捉到一个click事件,我们调用stopPropagation和preventDefault。调用preventDefault能够阻止链接变为activated状态。 */this.clickbuster.onClick = function(event){for (var i = 0; i < clickbuster.coordinates.length; i += 2) {var x = clickbuster.coordinates[i];var y = clickbuster.coordinates[i + 1];if (Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) {event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);event.preventDefault ? event.preventDefault() : (event.returnValue = false);}}};if (isTouch) {// 不需要使用我们的自定义功能,因为我们只需要触摸设备上点击document.addEventListener('click', clickbuster.onClick, true);clickbuster.coordinates = [];}})(this);window.onload = function(){new FastButton(document.getElementById('id2'), function(){alert('click');});}

View Code

总结

基于这一点,你应该很容易就可以创建快速响应的按钮。通过一些奇特的方式,你能够使这些按钮看起来像是基于你的开发平台的本地按钮一样。已经有一些解决同样问题的移动javascript库可以使用了,但是我们还从未见过任何一个能够提供click事件的优雅降级或者幽灵点击事件的解决方案的js库。我们希望浏览器的开发者们能够在将来的版本中,通过当网站的缩放被禁止(通过使用viewport的meta标签)时,能直接触发click事件的方式解决这个问题。实际上,这已经是姜饼版安卓浏览器要解决的事情了。

英文原文:Creating Fast Buttons for Mobile Web Applications

转载于:https://www.cnblogs.com/niubenbit/p/3623550.html

为移动端网页构造快速响应按钮相关推荐

  1. uni-app - 最详细 H5 网页接入微信登录功能,提供公众号配置与详细注释示例代码(移动端网页实现点击登录按钮后 调用微信公众号授权登录功能 详细讲解接入流程与详细示例代码)官方最新超级详细教程

    前言 关于 uni-app 项目中接入微信授权登录的文章鱼龙混杂,各种乱代码.过时.没注释.不讲流程原理,非常难用. 本文实现了 uni-app H5 移动端网页项目,实现微信授权登录功能,详细讲解接 ...

  2. 网络爬虫中Fiddler抓取PC端网页数据包与手机端APP数据包

    1 引言 在编写网络爬虫时,第一步(也是极为关键一步)就是对网络的请求(request)和回复(response)进行分析,寻找其中的规律,然后才能通过网络爬虫进行模拟.浏览器大多也自带有调试工具可以 ...

  3. javaScript PC端网页特效

    PC端网页特效 1. 元素偏移量 offset 系列 1.1 offset 概述 1.2 offset 与 style 区别 2. 元素可视区 client 系列 2.1 立即执行函数 2.2 loa ...

  4. 推荐3款移动端网页开发调试神器

    web前端教程 用大白话,来讲编程 最近有小伙伴在微信上跟我聊到了移动端网页开发调试困哪的问题,这个相信很多前端开发者都遇到过. 有一天,测试妹子拿着测试手机过来找你,说页面打不开. 你心想:怎么可能 ...

  5. 【移动端网页布局】移动端网页布局基础概念 ① ( 移动端浏览器 | 移动端屏幕分辨率 | 移动端网页调试方法 )

    文章目录 一.移动端浏览器 二.移动端屏幕分辨率 三.移动端网页调试方法 一.移动端浏览器 移动端浏览器 比 PC 端浏览器发展要晚 , 使用的技术比较新 , 对 HTML5 + CSS3 支持较好 ...

  6. 小程序嵌入web-view网页后,点击网页中的按钮跳转回小程序

    1.首先在网页端引入js <script type="text/javascript" src="https://res.wx.qq.com/open/js/jwe ...

  7. PC端和移动端网页特效,fastclick插件,Swiper插件,Bootstrap等框架,本地存储

    目录 PC 端网页特效 元素偏移量 offset 系列 1.offset 系列常用属性 2.offset 与 style 区别 3.计算鼠标在盒子内的坐标 4.模态框拖拽 5.京东商品放大镜 元素可视 ...

  8. web端 网页端分享功能的实现

    思路 web端 网页端分享功能的实现. 我们看微信的分享开发者文档,可以知道使用微信JS-SDK可以实现网页在微信里的分享. 微信JS-SDK说明文档 也就是说 在微信浏览器中打开的网页 才能调用 该 ...

  9. html5多屏互动游戏,多屏互动 —— 手机端与PC端 网页互动的现有尝试及设想

    不可否认,多屏时代已经到来. 手机/平板/笔记本/PC/TV等,多个显示平台的逐步构建,为信息传播及交互提供了多重平台及体验选择. 素材:多屏自适应网页设计/多屏延生设计 在此篇文章,取手机端与PC端 ...

最新文章

  1. java MD5 并发
  2. leetcode580. 统计各专业学生人数(SQL)
  3. numpy python 兼容_Python 2和3之间的numpy数组的不兼容性
  4. NPOI操作word文档
  5. freertos 创建互斥量_FreeRTOS的信号量和互斥量
  6. 海量存储——致性和高可用专题
  7. 湖南城市学院计算机题库和答案,湖南城市学院 计算机选择题题库
  8. HDU-5781 ATM Mechine(概率DP)
  9. VB.NET连接SQL数据库
  10. Linux 添加中文字体库
  11. 为知笔记linux输入中文,为知笔记wiznote无法输入中文,fcitx输入法问题解决
  12. 在python中for i in range是什么意思-Python for i in range ()用法详解
  13. 仓库管理一团糟,WMS仓库管理系统如何解决这些难点
  14. 腾讯云认证证书——云计算行业的敲门砖
  15. NetBeans IDE使用方法
  16. R语言入门(2)时间序列分析原理
  17. 视频前景提取 (III)【Mat版本】
  18. 微型计算机的型号是奔四800,第1章 微型计算机基础知识
  19. 使用DOS重定位技术执行isqlw(SQL查询分析器)
  20. simhash算法原理

热门文章

  1. 闰秒对数据库和linux的影响
  2. 《linux 网卡别名的添加和绑定》RHEL6
  3. Android 4.0 Launcher源码分析系列(二)
  4. 职场交流:一位软件工程师的7年总结
  5. 深圳敏捷云计算机科技,敏捷云 | 关于我们 | 敏捷云
  6. Pytorch GRU(详解GRU+torch.nn.GRU()实现)
  7. 按键精灵调用迅雷下载文件
  8. 计算机程序备份,将应用程序快照备份到计算机
  9. excel实战应用案例100讲(十二)-用Excel做一个自动抽奖器
  10. Linux程序选择boy糊者girl,linux脚本程序练习-Go语言中文社区