如何使用javascript

时间:2018-09-07 21:26:53

标签: javascript html css animation

我的任务是使用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>

2 个答案:

答案 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上的增量方向。唯一的区别是您需要分别跟踪xy的坐标,因为它们的方向相反。我用这个对象初始化到盒子的开始位置:

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 animationsJS canvasanimation framework来完成这类任务;这些工具将抽象出动画涉及的许多数学和状态表示。