requestAnimationFrame创建实例
1.先来一个简单的实时显示时间的功能吧
以下函数创建一个新Date()对象,使用toLocaleTimeString()提取一个时间字符串,然后在界面中显示它。然后,它使用每秒运行一次该函数setInterval(),从而创建每秒更新一次的数字时钟的效果
现在时刻:
<div id="demo"></div>
// 一个动态时间显示器
function displayTime() {
let date = new Date();
let time = date.toLocaleTimeString();
document.getElementById('demo').textContent = time;
}
const createClock = setInterval(displayTime, 1000);
2.制作旋转动画
1.存储对<div>
内部常量的引用,将rotateCount变量设置为0,设置未初始化的变量(稍后将用于包含对requestAnimationFrame()
调用的引用),并将startTime变量设置为null,稍后将用于存储的开始时间
2.插入一个draw()函数,该函数将用于包含我们的动画代码,其中包括timestamp参数
3.在draw()内部,添加以下内容:
如果尚未定义开始时间,它们将定义开始时间(这只会在第一次循环迭代中发生),并将rotateCount设置为一个旋转微调器(当前时间戳记,取开始时间戳记,除以三,以此类推)不会太快)
4.rotateCount将检查值是否在一个完整的圆上。如果是这样,它会将值设置为其模数360(即,将值除以时剩下的余数360),从而使圆形动画可以不间断地以合理的低值继续进行。请注意,这并非绝对必要,但使用0–359度的值比使用诸如的值更容易
5.实际旋转微调器
6.在draw()函数的最底部,插入以下行。这是整个操作的关键-您将先前定义的变量设置为活动requestAnimation()调用,该调用将draw()函数作为参数。这将启动动画,draw()以接近60 FPS的速率不断运行该功能。
//1
const spinner = document.querySelector('div');
let rotateCount = 0;
let startTime = null;
let rAF;
//2
function draw(timestamp) {
//4
if (rotateCount > 359) {
rotateCount %= 360;
}
//5
spinner.style.transform = `rotate(${rotateCount}deg)`;
//3
if (!startTime) {
startTime = timestamp;
}
rotateCount = (timestamp - startTime) / 3;
}
rAF = requestAnimationFrame(draw);
清除requestAnimationFrame()调用调用
cancelAnimationFrame(rAF);
设置CSS样式
html {
background-color: white;
height: 100%;
}
body {
height: inherit;
background-color: red;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
div {
display: inline-block;
font-size: 10rem;
}
3.一个反应小游戏
创建一个2人反应游戏。该游戏将有两名玩家,其中一位使用A键控制游戏,另一位使用L键。按下“ 开始”按钮后,将在5到10秒之间随机显示一个微调器(类似于我们之前看到的微调器)。在那之后,将出现一条消息,说"开始按键"-一旦发生这种情况,第一个按下其控制按钮的玩家将赢得比赛。
HTML部分
<div class="spinner" style="display: none;"><div><p>↻</p></div></div>
<section class="ui">
<div class="topbar">
<p class="p1">玩家1: 按"A"</p>
<p class="p2">玩家2: 按"L"</p>
<div class="middlebar">
<button>开始游戏</button>
<p class="result" style="display: none;"></p>
</div>
</div>
</section>
CSS部分
html {
background-color: blue;
height: 100%;
}
body {
height: inherit;
background-color: red;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
div {
display: inline-block;
font-size: 10rem;
}
spinner {
position: absolute;
z-index: 1;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.spinner div {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.spinner p {
margin: 0;
font-size: 10rem;
}
section {
width: 100%;
height: inherit;
padding: 30px;
}
.topbar {
height: 50%;
display: flex;
justify-content: space-between;
}
.topbar .p1 {
order: 0;
border-color: yellow;
color: yellow;
}
.topbar p, button {
margin: 0;
font-size: 1.5rem;
border: 5px solid;
border-radius: 20px;
padding: 10px 20px;
}
.p1, .p2 {
align-self: flex-start;
}
.topbar .p2 {
order: 2;
border-color: cyan;
color: cyan;
}
.topbar .middlebar {
order: 1;
}
.middlebar {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
button {
border: 0;
padding: 12.75px 20px;
background-color: #ddd;
cursor: pointer;
}
.topbar p, button {
margin: 0;
font-size: 1.5rem;
border: 5px solid;
border-radius: 20px;
padding: 10px 20px;
}
JS部分
一、
1.对微调器的引用,因此可以对其进行动画处理。
2.对<div>
包含微调框的元素的引用,用于显示和隐藏它。
3.轮换计数。这决定了您希望显示在动画的每一帧上旋转的微调器多少。
4.开始时间为空。当微调器开始旋转时,它将以开始时间填充。
5.一个未初始化的变量,用于以后存储requestAnimationFrame()对微调器进行动画处理的调用。
6.对“开始”按钮的引用。
7.对结果段落的引用。
二、只需要两个数字并在两个数字之间返回一个随机数。您稍后将需要它来生成随机超时间隔。
三、添加draw()功能,使微调器动画
四、隐藏结果段落和微调框
五、定义一个reset()函数,该函数将应用设置回玩游戏后再次启动游戏所需的原始状态
六、start()函数调用draw()以启动微调器旋转并在UI中显示它,隐藏“ 开始”按钮,这样您就无法通过同时启动多次来弄乱游戏,并运行在5到5之间的随机间隔后setTimeout()运行setEndgame()函数的调用10秒过去了。下面的块还将一个事件侦听器添加到您的按钮上,以在start()单击该函数时运行该函数
//一、
const spinner = document.querySelector('.spinner p');
const spinnerContainer = document.querySelector('.spinner');
let rotateCount = 0;
let startTime = null;
let rAF;
const btn = document.querySelector('button');
const result = document.querySelector('.result');
//二、
function random(min,max) {
var num = Math.floor(Math.random()*(max-min)) + min;
return num;
}
//三、
function draw(timestamp) {
if(!startTime) {
startTime = timestamp;
}
rotateCount = (timestamp - startTime) / 3;
if(rotateCount > 359) {
rotateCount %= 360;
}
spinner.style.transform = 'rotate(' + rotateCount + 'deg)';
rAF = requestAnimationFrame(draw);
}
//四、
result.style.display = 'none';
spinnerContainer.style.display = 'none';
//五、
function reset() {
btn.style.display = 'block';
result.textContent = '';
result.style.display = 'none';
}
//六、
btn.addEventListener('click', start);
function start() {
draw();
spinnerContainer.style.display = 'block';
btn.style.display = 'none';
setTimeout(setEndgame, random(5000,10000));
}
1.首先,使用取消微调器动画cancelAnimationFrame()(清理不需要的进程总是好方法),然后隐藏微调器容器。
2.接下来,显示结果段落并将其文本内容设置为“开始按键”。向玩家发出信号,表示他们现在可以按下按钮来获胜。
3.将keydown事件侦听器附加到文档。当按下任何按钮时,该keyHandler()功能将运行。
4.在内部keyHandler(),代码包含事件对象作为参数(由表示e)-它的key属性包含刚刚按下的键,您可以使用它来响应特定动作的特定按键。
5.将变量设置isOver为false,这样我们就可以跟踪是否按下了正确的按键以使玩家1或2获胜。我们不希望游戏在按下错误的键后结束。
6.登录e.key到控制台,这是找出key所按的不同键的值的有用方法。
7.当e.key为“ a”时,显示消息说玩家1获胜;当e.key为“ l”时,显示消息说玩家2获胜。(注意: 这仅适用于小写的a和l-如果提交了大写的A或L(加号Shift,则视为另一个键!)如果按下其中一个键,请将设置isOver为true。
8.只有当isOver是true,删除keydown事件侦听器使用removeEventListener(),因此一旦获胜按已经发生了,没有更多的键盘输入,可以把事情弄成最后一场比赛的结果
function setEndgame() {
cancelAnimationFrame(rAF);
spinnerContainer.style.display = 'none';
result.style.display = 'block';
result.textContent = '开始按键';
document.addEventListener('keydown', keyHandler);
function keyHandler(e) {
let isOver = false;
console.log(e.key);
if (e.key === "a") {
result.textContent = 'Player 1 won!!';
isOver = true;
} else if (e.key === "l") {
result.textContent = 'Player 2 won!!';
isOver = true;
}
if (isOver) {
document.removeEventListener('keydown', keyHandler);
setTimeout(reset, 5000);
}
};
}
尝试一下吧~