| js .hover | css :active | |
|---|---|---|
| 触发时机 | touchend之后1~2个渲染帧 | touchstart和touchend之间 |
| 阻止传播 | 可以 | 无法 |
| 多指 | 基本满足 | 基本不满足 |
| 体验问题 | touchend后才触发,不够快 | webkit核active时有元素显现,默认会阻止click事件传播,包括html上的onclick写法。解决办法:active样式移到和click同一元素上,或在显现的元素上加pointer-events: none; |
实现效果对比
js .hover
inner
inner
css :active
inner
inner
hover 代码
(function ($) {
$.extend($.fn, {
/**
* @param {String} s,动态绑定的对象,多个的话用逗号分隔
* @param {Number} time,tap最少响应时间,和客户端一致150ms
* @demo $(o).hover({s: 'xx, yy'})
*/
hover: function (options) {
const opts = {
s: '',
time: 150
}
// hover空间下存储当前对象
const $cur = $('');
// 存储多触点st
const _t = {};
let isMoved = false;
const _requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
for (let i in options) {
opts[i] = options[i]
}
$(this).on('touchstart', opts.s, function (e) {
const touches = e.touches;
$cur = $(this);
for (let i = 0; i < touches.length; i++) {
// 过滤未离开的、相临同一dom的
if (_t[touches[i].identifier] === undefined && (i == 0 || (i && (touches[i].target != touches[i - 1].target)))) {
_t[touches[i].identifier] = setTimeout(function () {
$cur.addClass('hover')
}, opts.time)
}
}
isMoved = false
}).on('touchmove', opts.s, function (e) {
// touchmove执行过快,简化处理
// 假定用户只用单指滑动
const touches = e.touches;
isMoved = true;
$(this).removeClass('hover');
clearTimeout(_t[touches[0].identifier]);
delete (_t[touches[0].identifier])
}).on('touchend', opts.s, function (e) {
const touches = e.changedTouches;
// 局部存储,保证逐个获得处理
const $cur = $(this);
// 浏览器目前输出一个,就不做touches.length循环了
// 清除不需要的st,以防st排队
clearTimeout(_t[touches[0].identifier]);
delete (_t[touches[0].identifier]);
if (isMoved || $cur.hasClass('hover')) {
$cur.removeClass('hover');
$cur = $('')
} else {
$cur.addClass('hover');
if (_requestAnimationFrame) {
// 使用2个requestAnimationFrame重绘新帧
_requestAnimationFrame(function () {
if ($cur.hasClass('hover')) {
_requestAnimationFrame(function () {
$cur.removeClass('hover')
})
}
})
} else {
// 1000/60取整,数字过小,部分手机会忽略而立即执行
setTimeout(function () {
$cur.removeClass('hover')
}, 17)
}
}
}).on('touchcancel', opts.s, function (e) {
const touches = e.changedTouches;
$cur = $(this);
clearTimeout(_t[touches[0].identifier]);
delete (_t[touches[0].identifier]);
$cur.removeClass('hover');
$cur = $('')
})
}
})
})($)