javascript - 如何让 Canvas 元素到达 Canvas 中心

标签 javascript html canvas

我在随机位置用圆弧填充 Canvas ,但现在我希望它们移动到 Canvas 的中心,但它们只是跳到 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();

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

最佳答案

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

更好的方法是使用基于原始点和中心之间的 Angular 矢量 - 类似于:

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
};

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

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>

关于javascript - 如何让 Canvas 元素到达 Canvas 中心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45749910/

相关文章:

javascript - 在javascript中加入多个回调/线程?

python - Tkinter ;如何在主根窗口中按下按钮时打开的弹出/顶级窗口中使用滚动条

javascript - 如何在不重定向的情况下提交多 HTML 表单

javascript - 无法读取未定义错误的属性 'getTime'

javascript - 按地理位置阻止 IP 地址

jquery - 在打开的菜单上使用 rgba 使页面变暗而不是使文本颜色变暗

html - 带有下拉菜单的语义 UI "three inline fields"

html - 表格内 CSS 跨度高度 100%

javascript - HTML Canvas - 拖动上传的图像并调整其大小

javascript - Div 覆盖 Canvas ,鼠标悬停