首页 > 解决方案 > 画布绘制一次,翻译一次,一次没有错误

问题描述

我已经采取了几乎所有可能的对策来防止我的程序在图表上绘制两个点而不是一个点。我希望显示中间的点,而不是左上角的点。在我看来,点在左上角被绘制一次,与坐标和所有内容匹配,但随后它用该translate方法绘制了第二个点。当然,这只是对屏幕上发生的事情的猜测。问题发生在draw()函数、init()函数或anim()函数的某个地方——我无法确定问题出在哪里。

let graph = document.getElementById('chart');
let c = graph.getContext('2d');
graph.height = 754;
graph.width = 754;

function algebra() {

  xVertex = 2 * 10;
  yVertex = 5 * 10;

  let radius = 3;
  let node = [];


  function Node(xVertex, yVertex, radius) {
    this.r = radius;
    this.xV = xVertex;
    this.yV = yVertex;

    this.draw = function() {
      c.beginPath();
      c.arc(this.xV, this.yV, this.r, 0, Math.PI * 2, false);
      c.fillStyle = "red";
      c.fill();
      c.translate(377, 377);
      c.stroke();
      c.closePath();
    };

    this.update = function() {
      this.draw();

    };
  };

  function init() {
    node.push(new Node(xVertex, yVertex, radius));
    anim();
  };

  function anim() {
    requestAnimationFrame(anim);
    for (let i = 0; i < node.length; i++) {
      node[i].update(node);
    };
    c.clearRect(0, 0, graph.width, graph.height);
    console.log(node);
  };
  init();
};
#graph {
  left: 100px;
  background-color: grey;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title> Proof of concept </title>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>

<body>
  <div id="graph">
    <canvas id="chart"></canvas>
    <div id="y-axis"></div>
    <div id="x-axis"></div>
  </div>
  <div id="button" onclick="algebra()">
    <div id="btext">Calculate</div>
  </div>

  <script type="text/javascript" src="app.js"></script>
</body>

</html>

标签: javascripthtmlcanvas

解决方案


我想我发现了你的错误:

1)调用anim()时必须先清除画布,然后重绘所有点。

2) 在画布上绘制完所有点后调用下一个动画帧

主要问题:

3)您正在对绘制的每个点(以及一个大点(377、377))进行画布原点的平移。由于原点在每次迭代或绘制点时都在变化,因此被擦除的画布部分也在移动。你得到的两点是第一次和第二次迭代,其他的都在屏幕外。

您需要做的是将画布原点仅翻译一次到它的中间,紧接着:

let c = graph.getContext('2d');
graph.height = 754;
graph.width = 754;

//Translate the origin to the canvas' center (do this only once)
c.translate(graph.width/2, graph.height/2);

如果画布原点已移动到中心,那么您还必须将画布从 -width/2 擦除到 width/2 和 height/2 到 height/2。为此,您必须使用:

c.clearRect(-graph.width/2, -graph.height/2, graph.width, graph.height);

只是为了好玩,我在节点数组中添加了三个点,并在每次迭代中为每个坐标添加了一个介于 -1 和 1 之间的随机数。这会产生类似布朗运动的模拟。

let graph = document.getElementById('chart');
let c = graph.getContext('2d');
graph.height = 754;
graph.width = 754;

//Translate the origin to the canvas' center (do this only once)
c.translate(graph.width/2, graph.height/2);


function algebra() {

  //Changed to 0 to plot at center
  xVertex = 0;
  yVertex = 0;

  let radius = 3;
  let node = [];


  function Node(xVertex, yVertex, radius) {
    this.r = radius;
    this.xV = xVertex;
    this.yV = yVertex;

    this.draw = function() {      
      c.beginPath();
      c.arc(this.xV, this.yV, this.r, 0, Math.PI * 2, false);
      c.fillStyle = "red";
      c.fill();
      c.stroke();
      c.closePath();
    };

    this.update = function() {
      //this will generate random movement in x and y.
      this.xV += Math.random()*2-1;
      this.yV += Math.random()*2-1;
      this.draw();
    };
  };

  function init() {
    node.push(new Node(xVertex, yVertex, radius));
    node.push(new Node(xVertex, yVertex, radius));
    node.push(new Node(xVertex, yVertex, radius));
    node.push(new Node(xVertex, yVertex, radius));
    anim();
  };

  function anim() {
    //First clear the canvas then redraw
    c.clearRect(-graph.width/2, -graph.height/2, graph.width, graph.height);
    for (let i = 0; i < node.length; i++) {
      node[i].update(node);
    };
    //After all are drawn, call the next Animation Frame
    requestAnimationFrame(anim);
  };
  init();
};
#graph {
  left: 100px;
  background-color: grey;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title> Proof of concept </title>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>

<body>
  <div id="graph">
    <canvas id="chart"></canvas>
    <div id="y-axis"></div>
    <div id="x-axis"></div>
  </div>
  <div id="button" onclick="algebra()">
    <div id="btext">Calculate</div>
  </div>

  <script type="text/javascript" src="app.js"></script>
</body>

</html>


推荐阅读