如何基于jQuery长按插件实现关联时长的自定义动画
解决jQuery长按插件随时长变化的自定义动画问题
我明白你的痛点——原来的长按插件只在长按完成后触发回调,所以你尝试的类添加或者CSS steps动画根本没法在长按过程中实时生效。问题的核心是:我们需要在长按的持续过程中,实时追踪已按下的时长,并把这个时长转化为动画进度,而不是等结束才一次性处理。
原插件的局限性
不管是原版还是你的更新版,核心逻辑都是用setTimeout在指定时长后触发长按完成的回调。这种方式只能在“结束”节点执行操作,无法捕捉长按过程中的每一刻状态,自然没法驱动随时间变化的动画。
修改思路:添加实时进度追踪
我们可以在用户按下(mousedown/touchstart)时启动一个重复定时器(比如每10ms执行一次),每次计算当前已长按的时间占总时长的比例,再用这个比例来控制动画参数(比如背景色、宽度、透明度等)。当长按取消或完成时,再清除这个定时器。
修改后的完整插件代码
基于你的更新版插件,我添加了实时进度追踪的逻辑:
(function($) { $.fn.longpress = function(longCallback, duration) { // 设置默认参数 let defaults = { click: function(el, e) {}, start: function(el, e) { el.css("color", "#000"); }, // 新增:实时更新动画的回调,参数是当前长按进度(0到1之间) progress: function(el, e, ratio) { // 默认实现:背景色从#fff过渡到#000 const r = Math.floor(255 * (1 - ratio)); const g = Math.floor(255 * (1 - ratio)); const b = Math.floor(255 * (1 - ratio)); el.css("backgroundColor", `rgb(${r}, ${g}, ${b})`); }, complete: function(el, e) { el.css("color", "#FFF"); // 长按完成后固定背景色为#000 el.css("backgroundColor", "#000"); }, cancel: function(el, e) { el.css("color", "#F00"); // 取消后恢复背景色为#fff el.css("backgroundColor", "#fff"); }, duration: 1000 }; // 合并用户配置 let options = $.extend({}, defaults); // 如果传入了duration,覆盖默认值 if (typeof duration === "number") { options.duration = duration; } return this.each(function() { var $this = $(this); var mouse_down_time; var timeout; var progressInterval; // 新增:实时进度的定时器 $this.data("clicked", "false"); // 按下时的回调 function mousedown_callback(e) { options.start($this, e); $this.data("clicked", "true"); mouse_down_time = new Date().getTime(); var context = $(this); // 启动实时进度定时器:每10ms更新一次 progressInterval = setInterval(function() { const press_time = new Date().getTime() - mouse_down_time; // 计算进度比例,最大为1(避免超过总时长后继续变化) const progressRatio = Math.min(press_time / options.duration, 1); // 调用进度回调,传递当前比例 options.progress($this, e, progressRatio); }, 10); // 原有的长按完成定时器 timeout = setTimeout(function() { if (typeof longCallback === "function") { longCallback.call(context, e); options.complete($this, e); $this.data("clicked", "false"); // 完成后清除进度定时器 clearInterval(progressInterval); } else { $.error('Callback required for long press. You provided: ' + typeof longCallback); } }, options.duration); } // 松开时的回调 function mouseup_callback(e) { var press_time = new Date().getTime() - mouse_down_time; if (press_time < options.duration) { clearTimeout(timeout); // 取消进度定时器 clearInterval(progressInterval); $this.data("clicked", "false"); options.click($this, e); // 短按后恢复初始状态 options.cancel($this, e); } else { // 如果长按时间刚好达标,确保清除进度定时器 clearInterval(progressInterval); } } // 移动时取消长按的回调 function move_callback(e) { let isClicked = $this.data("clicked"); if (isClicked == "false") return; options.cancel($this, e); clearTimeout(timeout); // 取消进度定时器 clearInterval(progressInterval); $this.data("clicked", "false"); } // 绑定事件 $this.on('mousedown', mousedown_callback); $this.on('mouseup', mouseup_callback); $this.on('mousemove', move_callback); $this.on('touchstart', mousedown_callback); $this.on('touchend', mouseup_callback); $this.on('touchmove', move_callback); }); }; }(jQuery));
使用示例
你可以直接调用这个插件,甚至自定义progress回调来实现不同的动画效果:
// 示例1:默认背景色过渡(#fff到#000) $("#myElement").longpress(function() { // 长按完成后的逻辑 alert("长按完成!"); }, 2000); // 长按时长设为2秒 // 示例2:自定义进度动画(比如宽度从100%到50%) $("#anotherElement").longpress(function() { alert("长按完成!"); }, { duration: 1500, progress: function(el, e, ratio) { // 宽度从100%过渡到50% const width = 100 - (50 * ratio); el.css("width", `${width}%`); }, complete: function(el) { el.css("width", "50%"); }, cancel: function(el) { el.css("width", "100%"); } });
额外优化建议
- 如果想要更流畅的动画,可以把
setInterval换成requestAnimationFrame,它会根据浏览器的刷新频率来执行,性能更好。 - 可以通过CSS变量(
--progress)来控制动画,这样能把样式逻辑和JS分离,比如在progress回调里设置el.css("--progress", ratio),然后在CSS里写background: linear-gradient(#000, #fff) calc(var(--progress)*100%) 0/100% 100% no-repeat;。
内容的提问来源于stack exchange,提问作者markb
相关产品推荐
相关产品推荐

