Open douchaoyang opened 1 year ago
在日常开发中常碰到抽奖类的需求,如“九宫格”,“翻牌”等以循环计步最后减速落在某一位置的形式。
此类问题可形象的模拟为一段跑步,加速-匀速-减速,这里简化为匀速-减速模式。
曲线方程大致为:
我的设想为,横坐标代表步数,纵坐标代表从当前落脚点到下一个落脚点所花的时间(ms)。 初始时间设为100ms,终点设为1100ms(方便计算),拐点从距离终点5步开始。 设常量总步数为 k。 所得方程为y = 40 * (x - (k - 5)) ** 2
ms
100ms
1100ms
5
k
y = 40 * (x - (k - 5)) ** 2
function 参数有 total、start、stop、loop、cb total 是代表跑完一圈需要多少步,比如九宫格去掉中间的按钮就是8。 start 是开始的落脚点,设置这个参数是因为多次抽奖需从上一次抽奖的落脚点开始。 stop 是结束的落脚点。 loop 是需要循环的次数。 cb 是一个回调函数,参数为每次的计步点,比如 total 为 8,参数每次返回就是 1 2 3 4 5 6 7 8 1 2 3...
function
total
start
stop
loop
cb
8
1 2 3 4 5 6 7 8 1 2 3...
实现为:
function runtowalk({ total, start, stop, loop, cb }) { return new Promise((resolve, reject) => { var step = total - start + total * loop + stop; var foot = 1; function y(x, k) { return 40 * (x - k + 5) ** 2; } // 运行匿名函数,接收 callee (function () { cb(((foot - 1 + start - 1 + total) % total) + 1); var time = foot > step - 5 ? y(foot, step) : 100; if (foot <= step) { foot++; setTimeout(arguments.callee, time); } else { resolve(((foot - 1 + start - 1 + total) % total) + 1); } })(); }); }
其中 step 为所需要的总步数,function y 是减速函数。
step
function y
例(html):
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>抽奖计步器</title> <style> table { width: 600px; height: 600px; } td { width: 30%; text-align: center; } .active { background-color: #ccc; } </style> <script src="https://file.eefcdn.com/campaign/eefocus/js/jquery.min.js"></script> </head> <body> <table border="1"> <tr> <td class="step step1">1</td> <td class="step step2">2</td> <td class="step step3">3</td> </tr> <tr> <td class="step step8">8</td> <td id="start">开始</td> <td class="step step4">4</td> </tr> <tr> <td class="step step7">7</td> <td class="step step6">6</td> <td class="step step5">5</td> </tr> </table> <script> function runtowalk({ total, start, stop, loop, cb }) { return new Promise((resolve, reject) => { var step = total - start + total * loop + stop; var foot = 1; function y(x, k) { return 40 * (x - k + 5) ** 2; } // 运行匿名函数,接收 callee (function () { cb(((foot - 1 + start - 1 + total) % total) + 1); var time = foot > step - 5 ? y(foot, step) : 100; if (foot <= step) { foot++; setTimeout(arguments.callee, time); } else { resolve(((foot - 1 + start - 1 + total) % total) + 1); } })(); }); } var start = 1; $("#start").on("click", function () { var stop = Math.ceil(Math.random() * 8); console.log("stop", stop); runtowalk({ total: 8, start: start, stop: stop, loop: 2, cb(a) { console.log(a); $(".step").removeClass("active"); $(".step" + a).addClass("active"); }, }).then((end) => { start = end; }); }); </script> </body> </html>
在日常开发中常碰到抽奖类的需求,如“九宫格”,“翻牌”等以循环计步最后减速落在某一位置的形式。
此类问题可形象的模拟为一段跑步,加速-匀速-减速,这里简化为匀速-减速模式。
曲线方程大致为:
我的设想为,横坐标代表步数,纵坐标代表从当前落脚点到下一个落脚点所花的时间(
ms
)。 初始时间设为100ms
,终点设为1100ms
(方便计算),拐点从距离终点5
步开始。 设常量总步数为k
。 所得方程为y = 40 * (x - (k - 5)) ** 2
function
参数有total
、start
、stop
、loop
、cb
total
是代表跑完一圈需要多少步,比如九宫格去掉中间的按钮就是8
。start
是开始的落脚点,设置这个参数是因为多次抽奖需从上一次抽奖的落脚点开始。stop
是结束的落脚点。loop
是需要循环的次数。cb
是一个回调函数,参数为每次的计步点,比如total
为8
,参数每次返回就是1 2 3 4 5 6 7 8 1 2 3...
实现为:
其中
step
为所需要的总步数,function y
是减速函数。例(
html
):