我的任务是使用JavaScript制作动画。
基本上,我有两个正方形(红色和黄色)和两个按钮(按钮1和按钮2)。
当我单击button1
时,红色方块从(左上角)到(右下角)。
我需要创建另一个按钮(button2
),以便在单击该按钮时,我需要红色方块返回到开头。
我需要它做相反的移动(从右下角移动到左上角)。
我应该在第二个功能中进行哪些更改?
这是代码
function myMove1() {
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
function myMove2() {
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<p>
<button onclick="myMove1()">button 1</button>
<button onclick="myMove2()">button 2</button>
</p>
<div id="container">
<div id="animate"></div>
</div>
答案 0 :(得分:2)
我将假设老师正在尝试教授基本的javascript,并告诉您如何使用您提供的部分解决这个问题。
也就是说,您的评论者是正确的,requestAnimationFrame是此处的正确工具。此外,您间隔的5毫秒延迟确实很短(125fps)。如果您输入了这个数字,建议您将其更改为16,大约为60fps。
<form action="https://stackoverflow.com/questions/52229901/navigate-to-route-on-button-click/">
<input type="submit" value="Visit Website"/>
</form>
// We want each function to be able to see these vars.
var pos = 0;
// Either -1, 0, or 1, depending on if were moving forward, backwards or
// stopped.
var direction = 0;
// This var now serves dual purpose, either its a number which is the
// interval id or its falsy, which we can use to understand the animation
// has stopped.
var id = null;
// Doing this here, will save the browser from having to redo this step on
// each frame.
var elem = document.getElementById("animate");
// Render the elem to the correct starting location.
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
// A single animation function.
function frame() {
// Assume we are heading for 350.
var goal = 350
if (direction < 0) {
// unless the goal is -1, when the goal is zero.
goal = 0
}
if (pos != goal) {
pos += direction;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
} else {
// Reset all the shared vars.
direction = 0;
clearInterval(id);
id = null;
}
}
function myMove1() {
if (id) {
clearInterval(id)
}
direction = 1;
id = setInterval(frame, 5);
}
function myMove2() {
if (id) {
clearInterval(id)
}
direction = -1;
id = setInterval(frame, 5);
}
#animate {
position: absolute;
width: 10px;
height: 10px;
background-color: red;
}
答案 1 :(得分:0)
您要问的很简单:采用您已经编写的函数并更改pos
上的增量方向。唯一的区别是您需要分别跟踪x
和y
的坐标,因为它们的方向相反。我用这个对象初始化到盒子的开始位置:
pos = {x: 350, y: 0};
function myMove1() {
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
function myMove2() {
var elem = document.getElementById("animate");
var pos = {x: 350, y: 0};
var id = setInterval(frame, 5);
function frame() {
if (pos.y >= 350 || pos.x <= 0) {
clearInterval(id);
} else {
pos.x--;
pos.y++;
elem.style.top = pos.y + 'px';
elem.style.left = pos.x + 'px';
}
}
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<p>
<button onclick="myMove1()">button 1</button>
<button onclick="myMove2()">button 2</button>
</p>
<div id="container">
<div id="animate"></div>
</div>
但是,这些函数不能在没有参数的情况下重用;这段代码是WET(将所有内容写两次)。动画很脆弱,因为每次单击都会创建新的超时(您可以向按钮发送垃圾邮件,并观察其崩溃)。动画中的实体没有状态。如果要更改位置或添加另一个框,则必须重新编写并复制所有代码。
牢记这一点,这是一个草图,用于说明有些改进的版本,可以作为思想的食粮。函数和对象更为通用,不需要为您决定添加的新动作而重写。 Box
类跟踪一段时间内的实体状态。 requestAnimationFrame()
用于立即更新和绘制屏幕上的所有实体,从而避免了setTimeout
的许多问题。
const lerp = (v0, v1, t) => (1 - t) * v0 + t * v1;
const dist = (a, b) => ((a.x - b.x) ** 2 + (a.y - b.y) ** 2) ** 0.5;
class Box {
constructor(elem, pos, size, color, speed) {
this.elem = elem;
this.speed = speed;
this.from = this.to = this.pos = pos;
this.t = 0;
this.elem.style.position = "absolute";
this.elem.style.background = color;
this.elem.style.height = `${size}px`;
this.elem.style.width = `${size}px`;
this.elem.style.top = `${this.pos.y}px`;
this.elem.style.left = `${this.pos.x}px`;
}
move(to) {
this.from = {x: this.pos.x, y: this.pos.y};
this.to = {x: to.x, y: to.y};
this.t = 0;
}
update() {
if (dist(this.pos, this.to) > 1) {
this.pos.x = lerp(this.from.x, this.to.x, this.t);
this.pos.y = lerp(this.from.y, this.to.y, this.t);
this.elem.style.top = `${this.pos.y}px`;
this.elem.style.left = `${this.pos.x}px`;
this.t += this.speed;
}
}
}
const data = [
{color: "red", pos: {x: 0, y: 0}, size: 10},
{color: "yellow", pos: {x: 350, y: 0}, size: 10},
];
const elems = document.getElementsByClassName("box");
const boxes = [];
for (let i = 0; i < elems.length; i++) {
boxes.push(new Box(elems[i], data[i].pos, data[i].size, data[i].color, 0.01));
}
function myMove1() {
boxes[0].move({x: 350, y: 350});
boxes[1].move({x: 0, y: 350});
}
function myMove2() {
boxes[0].move({x: 0, y: 0});
boxes[1].move({x: 350, y: 0});
}
(function render() {
boxes.forEach(e => e.update());
requestAnimationFrame(render);
})();
<p>
<button onclick="myMove1()">button 1</button>
<button onclick="myMove2()">button 2</button>
</p>
<div id="container">
<div class="box"></div>
<div class="box"></div>
</div>
最后,考虑使用CSS animations,JS canvas或animation framework来完成这类任务;这些工具将抽象出动画涉及的许多数学和状态表示。