JavaScript奇淫技巧:变速齿轮
字数 713 2025-08-11 21:26:35
JavaScript变速齿轮实现原理与教学文档
1. 概述
本文介绍如何使用JavaScript实现类似PC时代"变速齿轮"的功能,通过Hook技术改变网页中动画的时间流速,从而实现加速或减速效果。
2. 核心原理
通过Hook(钩子)技术接管JavaScript的定时器函数(如setTimeout),修改其时间参数,从而改变动画执行速度:
- 保存原始setTimeout函数的引用
- 重新定义setTimeout函数
- 在新的setTimeout函数中修改时间参数
- 调用原始setTimeout函数执行
3. 完整实现代码
<html>
<body>
<h1>JS变速齿轮DEMO</h1>
<button onclick="dec_speed();">减速</button>
<button onclick="add_speed();">加速</button>
<div id="box" style="margin: 10px; position: absolute; width: 90px; height: 90px; background: #00ffff; border-radius: 50px;"></div>
<script>
// 变速增量
var speed = 0;
// Hook setTimeout,实现变速
// 备份原始setTimeout函数
var pre_setTimeout = setTimeout;
// 新的setTimeout函数
var setTimeout = function(){
arguments[1] = arguments[1] + speed;
console.log("arguments", arguments[1]);
// 最小为1,1毫秒
if(arguments[1]<1) arguments[1] = 1;
// 执行回调函数
pre_setTimeout.apply(this, arguments);
}
// 加速
function add_speed(){
speed = speed - 20;
console.log("速度",speed)
if(speed < -100) speed = -100
}
// 减速
function dec_speed(){
speed += 20;
console.log("速度",speed)
if(speed > 200) speed = 200
}
// 小球移动动画
function move() {
var box = document.getElementById("box");
var current_position = 0;
var left = 1;
// 循环调用
function render() {
setTimeout(render, 100);
current_position += left;
if (current_position == 200 || current_position == 0){
left = -left;
}
box.style.left = current_position + "px";
}
render();
}
move();
</script>
</body>
</html>
4. 关键代码解析
4.1 Hook setTimeout
// 备份原始setTimeout函数
var pre_setTimeout = setTimeout;
// 新的setTimeout函数
var setTimeout = function(){
arguments[1] = arguments[1] + speed; // 修改时间参数
if(arguments[1]<1) arguments[1] = 1; // 确保最小为1ms
pre_setTimeout.apply(this, arguments); // 调用原始函数
}
arguments[1]对应setTimeout的第二个参数(延迟时间)- 通过修改这个值实现加速/减速效果
4.2 速度控制
var speed = 0; // 全局速度变量
// 加速
function add_speed(){
speed = speed - 20; // 减少延迟时间=加速
if(speed < -100) speed = -100 // 限制最大加速
}
// 减速
function dec_speed(){
speed += 20; // 增加延迟时间=减速
if(speed > 200) speed = 200 // 限制最大减速
}
4.3 动画实现
function move() {
var box = document.getElementById("box");
var current_position = 0;
var left = 1;
function render() {
setTimeout(render, 100); // 使用被Hook的setTimeout
current_position += left;
if (current_position == 200 || current_position == 0){
left = -left; // 反向移动
}
box.style.left = current_position + "px";
}
render();
}
5. 扩展应用
同样的原理可以应用于其他定时器函数:
5.1 Hook setInterval
var pre_setInterval = setInterval;
setInterval = function(){
arguments[1] = arguments[1] + speed;
if(arguments[1]<1) arguments[1] = 1;
return pre_setInterval.apply(this, arguments);
}
5.2 Hook requestAnimationFrame
var pre_requestAnimationFrame = requestAnimationFrame;
var lastTime = 0;
requestAnimationFrame = function(callback){
var currentTime = performance.now();
var timeToCall = Math.max(0, 16 - (currentTime - lastTime) + speed);
var id = pre_requestAnimationFrame(function(timestamp){
callback(timestamp);
});
lastTime = currentTime + timeToCall;
return id;
}
6. 代码保护
由于JavaScript代码是明文的,可以使用混淆工具(如JShaman)对代码进行加密保护,防止功能逻辑被轻易复制或分析。
7. 注意事项
- 最小时间限制:确保修改后的时间不小于1ms
- 速度边界检查:避免速度值过大或过小导致异常
- 兼容性:不同浏览器对最小定时器间隔的实现可能不同
- 性能影响:过度修改时间参数可能影响页面性能
8. 应用场景
- 网页游戏加速/减速
- 动画演示速度控制
- 测试环境模拟不同性能条件
- 教学演示时间相关概念
通过这种Hook技术,可以实现不修改原始动画逻辑的情况下,全局控制网页的时间流速,达到变速效果。