如何使canvas元素到达画布的中心

时间:2017-08-18 06:29:57

标签: javascript html5 canvas

我在随机位置用弧形填充画布,但现在我希望它们移动到画布的中心,但它们只是跳到画布的中心而不是慢慢移动到中心。 到目前为止的道路

<canvas id="myCanvas"></canvas>
<script>
    var myCanvas = document.getElementById("myCanvas");
    var c = myCanvas.getContext("2d");
    myCanvas.style.backgroundColor = "#000";
    myCanvas.width = 600;
    myCanvas.height = 600;
    var myArr = [];
    var firstCircle;

    function Circledraw(x, y, r) {
        this.x = x;
        this.y = y;
        this.r = r;

        this.draw = function() {
            c.beginPath();
            c.arc(this.x, this.y, this.r, 0, Math.PI * 2);
            c.fillStyle = "#fff";
            c.fill();
        }

        this.update = function() {
            this.x = myCanvas.clientWidth/2;
            this.y = myCanvas.clientHeight/2;
        }

    }

    for(var i =0; i < 10; i++){
        var x = Math.random() * myCanvas.clientWidth;
        var y = Math.random() * myCanvas.clientHeight;
        var r = 20;
        firstCircle = new Circledraw(x, y, 20);
        firstCircle.draw();
        myArr.push(firstCircle);
    }

    setInterval(circleFall, 1000);

    function circleFall() {
        c.clearRect(0,0, myCanvas.clientWidth, myCanvas.clientHeight);
        for(var z =0; z < myArr.length; z++){
            myArr[z].update();
            firstCircle.draw();
        }

    }


</script>

我如何解决这个问题?

编辑:

<script>
var canvas = document.getElementById("myCanvas"); var c = canvas.getContext("2d");
canvas.width = 600;
canvas.height = 600;
canvas.style.backgroundColor = "#e74c3c";

function Vectors(x, y, r) {
  this.x = x;
  this.y = y;
  this.r = r;

  var centerX = canvas.width/2;
  var centerY = canvas.height/2;

  var diffX = centerX - this.x;
  var diffY = centerY - this.y;
  var angle = Math.atan(diffY, diffX);
  var speed = 1;

  var vector = {
    x: Math.cos(angle) * speed,
    y: Math.sin(angle) * speed
  }

  this.draw = function() {
    c.beginPath();
    c.arc(this.x, this.y, this.r, 0, Math.PI * 2);
    c.fillStyle = '#fff';
    c.fill();
  }

  this.update = function() {  
        this.x += vector.x;
        this.y += vector.y;
  }

}

var newCircle = new Vectors(90, 100, 10);


function animate() {
  window.requestAnimationFrame(animate);
  c.clearRect(0, 0, canvas.width, canvas.height);
  newCircle.update();
  newCircle.draw();
}
animate();

第一个弧放置的是坐标而不是随机位置,但它没有向中心移动。

1 个答案:

答案 0 :(得分:2)

myCanvas.clientWidth/2myCanvas.clientHeight/2将始终返回相同的结果,在本例中为画布的中心点。

更好的方法是使用基于原点和中心之间角度的矢量 - 例如:

var diffX = myCanvas.width / 2 - this.x,
    diffY = myCanvas.height / 2 - this.y,
    angle = Math.atan2(diffY, diffX),
    speed = 1;

var vector = {
  x: Math.cos(angle) * speed,
  y: Math.sin(angle) * speed
};

然后在更新方法中将向量添加到位置:

this.update = function() {
  // todo add some checks here to see if it's close enough to center
  this.x += vector.x;
  this.y += vector.y;
}

将此与requestAnimationFrame()相结合而不是使用setInterval()将使动画丝绸顺畅。

var myCanvas = document.getElementById("myCanvas");
var c = myCanvas.getContext("2d");
myCanvas.style.backgroundColor = "#000";
myCanvas.width = 600;
myCanvas.height = 600;
var myArr = [];
var firstCircle;

function Circledraw(x, y, r) {
    this.x = x;
    this.y = y;
    this.r = r;
    
    var cx = myCanvas.width/2, 
        cy = myCanvas.height/2,
        diffX = cx - this.x,
        diffY = cy - this.y,
        angle = Math.atan2(diffY, diffX),
        speed = 1;

    var tolerance = 2; 
    var vector = {
      x: Math.cos(angle) * speed,
      y: Math.sin(angle) * speed
    };


    this.update = function() {
      if (!(this.x > cx - tolerance && this.x < cx + tolerance &&
          this.y > cy - tolerance && this.y < cy + tolerance)) {
        this.x += vector.x;
        this.y += vector.y;
      }
      else { /* this can be used to detect finished action */ }
    }

    this.draw = function() {
        c.beginPath();
        c.arc(this.x, this.y, this.r, 0, Math.PI * 2);
        c.fillStyle = "#fff";
        c.fill();
    }

}

for(var i =0; i < 10; i++){
    var x = Math.random() * myCanvas.width;
    var y = Math.random() * myCanvas.height;
    var r = 20;
    firstCircle = new Circledraw(x, y, 20);
    firstCircle.draw();
    myArr.push(firstCircle);
}

(function circleFall() {
    c.clearRect(0,0, myCanvas.clientWidth, myCanvas.clientHeight);
    for(var z =0; z < myArr.length; z++){
        myArr[z].update();
        myArr[z].draw();  // make sure to draw th current circle
    }
    requestAnimationFrame(circleFall);
})();
<canvas id="myCanvas"></canvas>

另一种方法是使用线性插值,允许点同时在中心完成:

var myCanvas = document.getElementById("myCanvas");
var c = myCanvas.getContext("2d");
myCanvas.style.backgroundColor = "#000";
myCanvas.width = 600;
myCanvas.height = 600;
var myArr = [];
var firstCircle;

function Circledraw(x, y, r, step) {
    var startX, startY;
    var cx = myCanvas.width / 2;
    var cy = myCanvas.height / 2;

    this.x = startX = x;
    this.y = startY = y;
    this.r = r;
    this.t = 0;
    this.step = step; // since we work with normalized values, this tend to be small

    function lerp(v1, v2, t) {     // linear interpolation
      return v1 + (v2 - v1) * t;   // t = [0.0, 1.0] 0 = v1, 1 = v2
    }
    
    this.update = function() {
      if (this.t <= 1) {
        this.x = lerp(startX, cx, this.t);  // set abs. position based on t
        this.y = lerp(startY, cy, this.t);
        this.t += this.step;                // increase step for t
      }
      else { 
        /* this can be used to detect finished action, for example resetting pos */ 
        this.x = startX = Math.random() * myCanvas.width;
        this.y = startY = Math.random() * myCanvas.height;
        this.t = 0;
      }
    }

    this.draw = function() {
        c.beginPath();
        c.arc(this.x, this.y, this.r, 0, Math.PI * 2);
        c.fillStyle = "#fff";
        c.fill();
    }

}

for(var i =0; i < 10; i++){
    var x = Math.random() * myCanvas.width;
    var y = Math.random() * myCanvas.height;
    var r = 20;
    firstCircle = new Circledraw(x, y, 20, Math.random() * 0.04 + 0.005);
    firstCircle.draw();
    myArr.push(firstCircle);
}

(function circleFall() {
    c.clearRect(0,0, myCanvas.clientWidth, myCanvas.clientHeight);
    for(var z =0; z < myArr.length; z++){
        myArr[z].update();
        myArr[z].draw();  // make sure to draw th current circle
    }
    requestAnimationFrame(circleFall);
})();
<canvas id="myCanvas"></canvas>