iScroll4.2.5中的无法滑动或点击的解决方案(转)
又见iScroll问题,特别是三星手机和iPhone,顺便提一句,现在的项目中他们给div加了height属性来解决不能滚动问题,个人认为是个非常愚蠢的解决方案,我必须使用media query来解决随之而来的不同手机有不同高度问题,既不能适应所有手机,万一将来有了新手机型号,也会发生问题。不过他们是公司专门雇佣的顾问和专家,我也没辙。
转载自: http://www.websqq.org/archives/1524,原文如下
iScroll(注4.2.5版本)框架在部分三星手机上无法滑动或点击的解决方案
一、测试平台
三星 i9023 android 4.1.2 (正常)
三星 i9250 android 4.2.2 (存在问题)
三星 i9300 android4.1.1 (存在问题)
三星 i9308 android 4.0.4 (存在问题)
二、问题描述
上述手机出现无法滑动或者无法触发点击事件的情况
三、问题分析
1、onBeforeScrollStart方法
此方法是在_start里进行了调用,目的是为了阻止浏览器默认动作的执行,防止在滑动的过程中进行干扰,同时也就阻止了滑动区域里元素的事件的触发,这种处理方式也直接导致了必须要在_end方法中再次触发元素的点击事件
2、_end方法
if (target.tagName != 'SELECT' && target.tagName != 'INPUT'
&& target.tagName != 'TEXTAREA') {
ev = document.createEvent('MouseEvents');
ev.initMouseEvent('click', true, true,
e.view, 1,point.screenX,
point.screenY, point.clientX,
point.clientY,e.ctrlKey,
e.altKey, e.shiftKey,
e.metaKey,0, null);
ev._fake = true;
target.dispatchEvent(ev);
}
这个处理方式就是顺承了上面所提到的阻止了浏览器默认行为后,对滑动区域除SELECT、INPUT、TEXTAREA外的元素触发click事件,已完成对click绑定事件的调用。
【具体分析】
由于onBeforeScrollStart是在_start方法中进行的调用,e.preventDefault();阻止了元素的默认行为,从而导致了元素绑定事件的失效,必须在_end操作结束后进行绑定事件的模拟调用,原始的iScroll源代码中在_end中最后创建了click事件的模拟,但是这里必须要清楚的一个原理就是,click其实是要依赖于其他事件的:
1) 普通pc网页中,click需要依赖于mousedown、mouseup的相继触发
2) 移动webkit中,click则需要依赖于touchstart、touchend(实际mousedown,mouseup在移动webkit上也存在)的相继触发
“相继触发”的意思就是中间不会夹杂有其他的事件类型,这也就很容易理解iScroll中在_end中对模拟事件调用的条件了,必须要判断that.moved才能直接触
发模拟事件。
iScroll中与_start、_move、_end相关的三个事件类型是按照如下的规则来设置的:
START_EV = hasTouch ? 'touchstart' : 'mousedown'
MOVE_EV = hasTouch ? 'touchmove' : 'mousemove'
END_EV = hasTouch ? 'touchend' : 'mouseup'
【注意事项】
经测试,三星部分手机里默认浏览器里会默认所有元素都有一个默认的click事件(测试结果显示鼠标事件中默认事件包含mouseup,mousedown,click,dblclick在移动webkit上不支持,为系统放大功能),e.preventDefault时会阻止掉默认click事件的执行,必须要人为的在_end结束之后模拟click事件的调用,而其他正常手机即使调用了e.preventDefault也不会阻止click事件的触发,因为这些手机的默认浏览器上的元素的click事件的cancelable属性不为true,不可以被preventDefault取消掉,会正常执行,而如果在_end中模拟了click事件则将会导致click的重复调用(在有toggle状态的事件上非常明显),因此折中的方式参见下面的解决方案。
四、解决方案
1. 去除onBeforeScrollStart里的阻止默认行为
2. onBeforeScrollMove设置为
以保证手机上的正常滑动免受浏览器默认行为影响(如下滑时会有窗口的scroll事件),当然如果这里不添加的话也可以在document的END_EV中阻止浏览器默认行为
3. _end 中将模拟事件名更改为END_EV或者直接去掉模拟事件的功能
iscroll.js是Matteo Spinelli开发的一个js文件,使用原生js编写,不依赖与任何js框架。旨在解决移动webkit系浏览器的区域滚动问题,兼容mobile safari、android默认浏览器、safari、chrome、firefox5+、opera11+、IE9+及其他webkit核心浏览器。最新版本为iscroll4。
iscroll的用武之地
1.区域滚动
我们在pc端web开发中,有时会用固定某一区域的宽度和高度,然后使用overflow:auto,使其内容在该区域内滚动。
iphone默认浏览器(mobile safari)也支持固定区域的滚动,但必须双指滑动操作,而且没有滚动条。mobile safari中的单指滑动只针对页面级别,不针对页面元素。这样的操作体验很麻烦,而且很多用户根本不知道双指能够区域滑动。
android自带浏览器也支持区域滚动,且可以单指滑动操作,但是滑动起来卡的半死半活,很不流畅。
使用iscroll,可以完美解决上述问题了,不仅可以在iphone和android上单指滑动,而且滑动起来流畅之极,酣畅淋漓。滑动过程中也有漂亮的滚动条提示,让你舒心不已。
2.固定定位
固定定位不是iscroll的原生用法,而是使用iscroll协助解决固定定位问题。
话说iphone很先进,但就是不支持position:fixed。这下苦了我们了,固定定位怎么解决啊,我们会经常遇到固定标题栏、固定工具栏等情况啊!!
使用iscroll协助解决:首先获取浏览器窗口高度;然后获取固定工具栏的高度;接着将除固定工具栏之外的内容全部放在一个固定区域内,该固定区域的高度=窗口高度-工具栏高度;之后对固定区域使用iscroll。这样,整个html页面的高度正好等于窗口高度,页面级别不会出现滚动,工具栏就一直固定在当前的位置。在固定区域内滑动,可以查看页面其他内容,不会影响工具栏的定位。
鼠标滚轮滚动
iscroll支持在pc端浏览器中使用鼠标滚轮控制区域滚动,但操作起来很不灵敏。这是由于iscroll对鼠标滚轮事件做了拦截,然后缩小了滚轮的滚动距离,详见iscroll4.js源代码608-609行:
wheelDeltaY = e.wheelDeltaY / 12;//控制Y轴鼠标滚轮速度
iscroll将每次的滚轮距离缩小为系统默认距离的12分之一,难怪滚起来很慢,感觉不灵敏。只需要将12改成1,滚轮的滚动速度就恢复正常了。你也可以根据实际需要设置成其他值。
输入框聚焦不灵敏、无法选择文字
使用了iscroll之后,你会发现点击输入框时不灵敏,经常无法聚焦;页面文字也无法选择和复制。这是由于iscroll要监听鼠标事件和触摸事件来进行滚动,所以禁止了浏览器的默认行为,详见源代码92行:
iscroll不分青红皂白,禁止了浏览器的一切默认行为,导致上述问题。所以我们需要稍作修改:
onBeforeScrollStart: function (e) {
var target = e.target;
while (target.nodeType != 1) target = target.parentNode;
if (target.tagName != ‘SELECT’ && target.tagName != ‘INPUT’ && target.tagName != ‘TEXTAREA’)
e.preventDefault();
}
判断触发事件的元素是不是input、select、textarea等表单输入类元素,如果不是就阻止默认行为。这样保证了输入类元素能正确快速聚焦。
在上述修改中追加一个条件 target.tagName != ‘body’或者直接将onBeforeScrollStart修改为null,即可做到鼠标选取文字,但这样的修改会导致iscroll滚动失效或不灵敏,所以无法选取文字这个问题先放一边吧。
select元素操作不灵敏或操作后白屏
使用iscroll后,还有一个较麻烦的问题,就是select元素点击不灵敏(滚动之后点击select,经常无响应);有时点击有反应了,下拉菜单显示却错位(pc端);选择一项之后,页面直接变成了空白(iphone、android中)或者页面位置向上偏离,滚动区域位置出现偏离。
说白了,就是导致select没法用。
为此我调试了很久,最后发现了问题所在:iscroll默认使用的是css的transform变形中的translate3d实现区域滚动,每次滚动实际是改变translate3d中的y轴值,实际的dom位置并没有发生变化。translate3d会导致页面的焦点错误,系统级下拉菜单的显示则会导致其出现显示偏离。
控制滚动模式的代码在67行:useTransform: true。好在iscroll提供了另一种滚动方式,基于绝对定位位置变化的滚动。
修改为useTransform: false之后,iscroll就会使用对定位位方式来实现滚动,该方式是我们在web开发中模拟动画的最常用方式,滚动之后dom的实际位置也同步发生了变化,不会出现错位偏离现象。
在pc端主流浏览器、iphone、android2.2下测试,select问题完美解决。
不过需要注意,使用对position决定定位后,滚动区的宽度默认会自适应内容宽度,而不是父元素的100%,所以最好将滚动区域宽度设为100%。
美中不足
iscroll是小而精的经典作品,名字也带着apple范。但唯一美中不足的是,只能使用id调用。
最近做移动平台的应用,使用iscroll使屏幕上下滑动。发现当使用iscroll后,input等不能输入内容了。只要在iscroll.js文件中加入如下代码就ok了。
function allowFormsInIscroll(){
[].slice.call(document.querySelectorAll('input, select, button')).forEach(function(el){
el.addEventListener(('ontouchstart' in window)?'touchstart':'mousedown', function(e){
e.stopPropagation();
})
})
}
document.addEventListener('DOMContentLoaded', allowFormsInIscroll, false);
iScroll4.2.5中的无法滑动或点击的解决方案(转)的更多相关文章
- ionic3中 ion-datetime 全屏可点击问题解决方案
废话不多说,能进来的都应该知道是个什么情况.我也是在网上找了一段时间,才在git上ionic官方团队的Issues中找到了问题解决方法. 第一,给外围包上一层ion-item,但是这有个问题,就是会让 ...
- android中无限循环滑动的gallery实例
android中无限循环滑动的gallery实例 1.点击图片有变暗的效果,使用imageview.setAlpha(),并且添加ontouchListener public void init() ...
- H5使用Swiper过程中遇到的滑动冲突
一.问题 (1)PC端可以鼠标可以拖动中间的轮子让页面上下滑动,点击左键按着也是拖不动 (2)手机端浏览H5手指不能滑动页面,导致很多页面下面的文字看不到 二.解决问题 1.下面分先说css的问题,主 ...
- Android中ViewPager实现滑动条及与Fragment结合的实例教程
ViewPager类主要被用来实现可滑动的视图功能,这里我们就来共同学习Android中ViewPager实现滑动条及与Fragment结合的实例教程,需要的朋友可以参考下 自主实现滑动指示条先上一个 ...
- PullToRefreshListView中嵌套ViewPager滑动冲突的解决
PullToRefreshListView中嵌套ViewPager滑动冲突的解决 最近恰好遇到PullToRefreshListView中需要嵌套ViewPager的情况,ViewPager 作为头部 ...
- iOS开发 横向分页样式 可左右滑动或点击头部栏按钮进行页面切换
iOS开发 横向分页样式 可左右滑动或点击头部栏按钮进行页面切换 不多说直接上效果图和代码 1.设置RootViewController为一个导航试图控制器 // Copyright © 2016年 ...
- Android 界面滑动卡顿分析与解决方案(入门)
Android 界面滑动卡顿分析与解决方案(入门) 导致Android界面滑动卡顿主要有两个原因: 1.UI线程(main)有耗时操作 2.视图渲染时间过长,导致卡顿 目前只讲第1点,第二点相对比较复 ...
- js手机端判断滑动还是点击
网上的代码杂七杂八, 我搞个简单明了的!! 你们直接复制粘贴, 手机上 电脑上 可以直接测试!!! 上图: 上代码: <!DOCTYPE html> <html lang=&q ...
- [转] c# 模拟Asp.net页面中的某个按钮的点击,向web服务器发出请求
在没有做题目中所述的内容的时候,感觉这应该是很简单的东西,但是当真正开始做的时候却发现,有很多问题现在在这里写出来,供和我一样水平不高的参考一下. 在写本文之前参照了一下文章 欢迎使用CSDN论坛阅读 ...
随机推荐
- Web前端开发规范文档
Web前端开发规范文档 规范目的: 使开发流程更加规范化. 通用规范: TAB键用两个空格代替(windos下tab键占四个空格,linux下TAB键占八个空格). CSS样式属性或者JAVASCRI ...
- svg学习(五)ellipse
<ellipse> 标签 <ellipse> 标签可用来创建椭圆.椭圆与圆很相似.不同之处在于椭圆有不同的 x 和 y 半径,而圆的 x 和 y 半径是相同的. <?xm ...
- php操作Mysql 以及封装常用的函数 用外连接连接3个表的案例
<?php header("content-type;text/html;charset=utf-8"); //数据库连接define('DB_HOST','localhos ...
- Leetcode: All O`one Data Structure
Implement a data structure supporting the following operations: Inc(Key) - Inserts a new key with va ...
- JS中同名函数有效执行顺序
html中如果出现函数同名时:如果有多个外部引入的js文件,例如a.js和b.js(引入顺序假定是a.js,然后是b.js),同时html中本身也有内部的js.那么针对 出现函数名一样的情况时,无论他 ...
- spring框架IoC
IoC反转控制, 举个反例: //数据操作类 public class DataBase { //向数据库中存储数据 public void saveDB() { } } //业务逻辑类 public ...
- 利用a标签特性解析地址(附加属性说明)
首先我们看看实例 a.href = 'http://www.cnblogs.com/wayou/p/'; console.log(a.host); 控制台会输出 "www.cnblogs.c ...
- jenkins+gerrit
Verified 功能 http://www.cnblogs.com/zhanchenjin/p/5032218.html
- Css Study - 纵向Menu - By html and Css
http://www.wikihow.com/Create-a-Dropdown-Menu-in-HTML-and-CSS HTML <div id="leftmenu"&g ...
- java中如何获取昨天的当前日期
在java里,获取昨天的当前日期,可以采用calendar来做,也可以采用date来做:如下: 1.采用calendar来做: Calendar cal=Calendar.getInstance(); ...