本文详细解析了使用JavaScript实现移动端下拉刷新的完整流程。通过监听touchstart、touchmove和touchend事件追踪滑动轨迹,利用CSS3的transform属性优化渲染性能并避免重绘。文章深入探讨了滑动距离判断、状态锁机制防止重复操作以及过渡动画的控制技巧,提供了从HTML结构到JS逻辑的完整代码示例,帮助开发者快速掌握下拉刷新功能的实现细节。
JavaScript下拉刷新实现概述
本文分享了一段JavaScript实现下拉刷新功能的示例代码,供读者参考学习。
HTML相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>
<body style="background-color: beige;">
<div id="container" style="width:100%;border:solid 1px blue; transform:translate(0px,-61px)">
<div style="height:50px; line-height:50px; text-align:center; width:100%; border:solid 1px red;">
努力加载中...
</div>
<div style="width:100%; line-height:30px;background-color:#F2F2F2; font-size:17px; font-family:'Adobe Garamond Pro'">
下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新
下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新
下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉拉刷新下拉刷新
</div>
</div>
</body>
</html>
<!--JQuery是那么的好用,这种情况下怎么能没有它呢!-->
<script type="text/javascript" src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script>
JavaScript核心逻辑与滑动轨迹处理
JavaScript需要完成哪些工作?
1、根据用户的滑动轨迹动态调整滑块的位置(通过transform中的translate属性实现);
2、根据滑动的距离来判断是否执行刷新操作(或加载新数据)。
此外,如果滑动结束后通过ajax重新加载页面数据,还需要处理页面向上滑动并隐藏提示部分的效果。
大致实现思路如下:
(前提条件:当前元素已滑动至顶部)
1、当鼠标左键按下(在移动设备上对应touchstart事件)时,记录当前鼠标位置的Y轴坐标;
2、当鼠标移动时(对应touchmove事件),实时记录鼠标的Y轴坐标,判断滑动轨迹并相应地移动滑块;
3、当鼠标左键松开(对应touchend事件)时,通过对比起始和结束Y轴坐标的距离,判断是否应该刷新页面(或重新加载数据)。
具体代码实现如下:
/*
*obj--滑动对象
*offset--滑动距离(当滑动距离大于等于offset时将调用callback)
*callback--滑动完成后的回调函数
*/
var slide = function (obj, offset, callback) {
var start,
end,
isLock = false,//是否锁定整个操作
isCanDo = false,//是否移动滑块
isTouchPad = (/hp-tablet/gi).test(navigator.appVersion),
hasTouch = 'ontouchstart' in window && !isTouchPad;
//将对象转换为jquery的对象
obj = $(obj);
var objparent = obj.parent();
/*操作方法*/
var fn =
{
//移动容器
translate: function (diff) {
obj.css({
"-webkit-transform": "translate(0," + diff + "px)",
"transform": "translate(0," + diff + "px)"
});
},
//设置效果时间
setTranslition: function (time) {
obj.css({
"-webkit-transition": "all " + time + "s",
"transition": "all " + time + "s"
});
},
//返回到初始位置
back: function () {
fn.translate(0 - offset);
//标识操作完成
isLock = false;
}
};
//滑动开始
obj.bind("touchstart", function (e) {
if (objparent.scrollTop() <= 0 && !isLock) {
var even = typeof event == "undefined" ? e : event;
//标识操作进行中
isLock = true;
isCanDo = true;
//保存当前鼠标Y坐标
start = hasTouch ? even.touches[0].pageY : even.pageY;
//消除滑块动画时间
fn.setTranslition(0);
}
});
//滑动中
obj.bind("touchmove", function (e) {
if (objparent.scrollTop() <= 0 && isCanDo) {
var even = typeof event == "undefined" ? e : event;
//保存当前鼠标Y坐标
end = hasTouch ? even.touches[0].pageY : even.pageY;
if (start < end) {
even.preventDefault();
//消除滑块动画时间
fn.setTranslition(0);
//移动滑块
fn.translate(end - start - offset);
}
}
});
//滑动结束
obj.bind("touchend", function (e) {
if (isCanDo) {
isCanDo = false;
//判断滑动距离是否大于等于指定值
if (end - start >= offset) {
//设置滑块回弹时间
fn.setTranslition(1);
//保留提示部分
fn.translate(0);
//执行回调函数
if (typeof callback == "function") {
callback.call(fn, e);
}
} else {
//返回初始状态
fn.back();
}
}
});
}
代码实现细节与性能优化分析
代码详细分析:
1、参数说明:obj表示需要滑动的DOM对象;offset表示触发回调的滑动距离阈值(例如代码中transform:translate(0px,-61px),此处offset为61);callback是滑动完成后的回调函数(用于执行页面刷新或数据加载)。
2、为什么选择transform而不是margin?
因为transform不会触发页面的重绘(repaint),相比margin能带来更流畅的视觉效果和更好的性能。但transform有一个特性:如果translateY的值为负数(即元素向上移动xx像素),下方的元素不会随之上移(而margin会带动下方元素上移),这是两者的主要区别。注意,代码中保留-webkit-transform前缀是必要的,因为部分浏览器(如微信内置浏览器)可能无法识别标准transform属性。为了兼容性,多写几个前缀是值得的。
3、关于将transition设置为0s的原因。
为什么要在touchstart时将transition的值设置为0秒?transition的作用是为元素属性变化添加过渡动画,例如设置transition为1s,元素将在1s内平滑变化。代码中设置transition的目的是在滑动结束后(手指离开屏幕)为滑块回弹添加过渡效果,使动画更自然。同时,该过渡效果也会应用于数据加载完成后提示部分的隐藏过程。将transition设为0是为了取消滑动过程中的过渡延迟,确保手指下按时滑块能即时跟随移动,实现“拖动”手感。如果不取消transition,滑动时会出现滑块抖动的现象(有兴趣者可尝试对比)。在整个过程中,transition的控制至关重要。
4、关于isLock和isCanDo变量。
这两个变量用于防止重复滑动。在第一次滑动且数据加载完成前,不允许进行第二次滑动。当滑动开始时,将isLock和isCanDo均设为true,允许后续事件中的代码正常运行;当滑动结束时,将isCanDo设为false,表示在isLock重置为true之前(即整个操作流程完成前),所有事件代码均不可用(不执行下拉加载等动作)。
5、如何使用该功能?
$(function () {
slide("#container", 61, function (e) {
var that = this;
setTimeout(function () {
that.back.call();
}, 2000);
});
});
以上就是本文的全部内容,希望对大家的学习有所帮助,也欢迎大家继续支持本站。