canvas:并非所有弹跳球对象数组中的对象都显示出来
canvas: not all objects in an array of bouncing ball objects are showing up
我使用 laravel 5.5、vuejs 和 vue-router 创建了一个 spa/rest/crud 应用程序。现在想到了使用一个组件作为登陆页面的想法,并用 canvas 来增加一点趣味。 (最初 p5.js,但我暂时放弃了。)到目前为止一切顺利。我让 Vue 组件通过 Vue-Router 工作,对于首页,我制作了一个带有自定义指令的组件,该指令向模板中的 canvas 元素提供其数据(以球对象的形式)
现在,由于我不得不切换到我不太熟悉的 Canvas,我 运行 遇到了问题。作为测试,我将 4 个球放入一个数组中。但只有 1 显示。现在,当我禁用 clearRect 功能时。他们确实以混乱的方式出现。我不得不使用 beginPath() 显然是为了防止球 'trailing'。但是当我这样做时,只会出现一个。也许这是我忽略的一件简单的事情。我将 post 我认为导致以下问题的部分:
<script>
export default {
data: function(){
return {
}
},
directives: {
bindCanvas: {
inserted: function (el) {
var ctx = el.getContext("2d");
var Ball = function(x,y,r){
this.position = {};
this.position.x = x;
this.position.y = y;
//i could not use vectors so i came up with this solution
this.velocity = {x:0,y:0};
this.acceleration = {x:0,y:0};
this.radius = r;
};
Ball.prototype.addForce = function(x,y){
this.acceleration.x += x/1000;
this.acceleration.y += y/1000;
};
Ball.prototype.move = function(){
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
this.velocity.x += this.acceleration.x;
this.velocity.y += this.acceleration.y;
//reset acceleration to 0
this.acceleration.x *= 0;
this.acceleration.y *= 0;
};
Ball.prototype.display = function(){
//here is the problem somewhere i think.
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
ctx.beginPath();
ctx.fillStyle = 'rgb(255,0,0)';
ctx.arc(this.position.x,this.position.y,this.radius,0, Math.PI*2);
ctx.fill();
};
Ball.prototype.checkBorders = function(){
if(this.position.x > ctx.canvas.width-(this.radius/2)){
this.velocity.x = this.velocity.x *-1;
} else if (this.position.x < 0){
this.velocity.x *= -1;
}
if (this.position.y > ctx.canvas.height-(this.radius/2)){
this.velocity.y *= -1;
} else if(this.position.y < 0){
this.velocity.y *= -1;
}
};
Ball.prototype.checkMaxSpeed = function(){
if(this.velocity.x > 0.5){
this.velocity.x = 0.5;
}
if(this.velocity.x < -0.5){
this.velocity.x = -0.5;
}
if(this.velocity.y > 0.5){
this.velocity.y = 0.5;
}
if(this.velocity.y < -0.5){
this.velocity.y = -0.5;
}
};
var arrayOfBalls = [];
for(var i=0;i<=3;i++){
arrayOfBalls.push(new Ball(Math.random()*100,Math.random()*100,Math.random()*100));
}
var animate = function(){
for(var j = arrayOfBalls.length-1; j>= 0; j--){
arrayOfBalls[j].checkBorders();
arrayOfBalls[j].checkMaxSpeed();
arrayOfBalls[j].addForce(Math.random(),Math.random());
arrayOfBalls[j].addForce(0,0.00098);
arrayOfBalls[j].display();
arrayOfBalls[j].move();
}
window.requestAnimationFrame(animate);
};
animate();
}
}
},
}
正如我在评论中提到的,问题是每个球的 display() 函数中的 clearRect() 调用。通常 canvas 只需要在动画的每个 frame/loop 中清除一次,因此 clearRect 可以放置在动画函数的顶部,如此处所示...
var animate = function(){
// Clear the canvas just once each animation frame here
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
for(var j = arrayOfBalls.length-1; j>= 0; j--) {
arrayOfBalls[j].checkBorders();
arrayOfBalls[j].checkMaxSpeed();
arrayOfBalls[j].addForce(Math.random(),Math.random());
arrayOfBalls[j].addForce(0,0.00098);
arrayOfBalls[j].display();
arrayOfBalls[j].move();
}
window.requestAnimationFrame(animate);
};
我使用 laravel 5.5、vuejs 和 vue-router 创建了一个 spa/rest/crud 应用程序。现在想到了使用一个组件作为登陆页面的想法,并用 canvas 来增加一点趣味。 (最初 p5.js,但我暂时放弃了。)到目前为止一切顺利。我让 Vue 组件通过 Vue-Router 工作,对于首页,我制作了一个带有自定义指令的组件,该指令向模板中的 canvas 元素提供其数据(以球对象的形式)
现在,由于我不得不切换到我不太熟悉的 Canvas,我 运行 遇到了问题。作为测试,我将 4 个球放入一个数组中。但只有 1 显示。现在,当我禁用 clearRect 功能时。他们确实以混乱的方式出现。我不得不使用 beginPath() 显然是为了防止球 'trailing'。但是当我这样做时,只会出现一个。也许这是我忽略的一件简单的事情。我将 post 我认为导致以下问题的部分:
<script>
export default {
data: function(){
return {
}
},
directives: {
bindCanvas: {
inserted: function (el) {
var ctx = el.getContext("2d");
var Ball = function(x,y,r){
this.position = {};
this.position.x = x;
this.position.y = y;
//i could not use vectors so i came up with this solution
this.velocity = {x:0,y:0};
this.acceleration = {x:0,y:0};
this.radius = r;
};
Ball.prototype.addForce = function(x,y){
this.acceleration.x += x/1000;
this.acceleration.y += y/1000;
};
Ball.prototype.move = function(){
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
this.velocity.x += this.acceleration.x;
this.velocity.y += this.acceleration.y;
//reset acceleration to 0
this.acceleration.x *= 0;
this.acceleration.y *= 0;
};
Ball.prototype.display = function(){
//here is the problem somewhere i think.
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
ctx.beginPath();
ctx.fillStyle = 'rgb(255,0,0)';
ctx.arc(this.position.x,this.position.y,this.radius,0, Math.PI*2);
ctx.fill();
};
Ball.prototype.checkBorders = function(){
if(this.position.x > ctx.canvas.width-(this.radius/2)){
this.velocity.x = this.velocity.x *-1;
} else if (this.position.x < 0){
this.velocity.x *= -1;
}
if (this.position.y > ctx.canvas.height-(this.radius/2)){
this.velocity.y *= -1;
} else if(this.position.y < 0){
this.velocity.y *= -1;
}
};
Ball.prototype.checkMaxSpeed = function(){
if(this.velocity.x > 0.5){
this.velocity.x = 0.5;
}
if(this.velocity.x < -0.5){
this.velocity.x = -0.5;
}
if(this.velocity.y > 0.5){
this.velocity.y = 0.5;
}
if(this.velocity.y < -0.5){
this.velocity.y = -0.5;
}
};
var arrayOfBalls = [];
for(var i=0;i<=3;i++){
arrayOfBalls.push(new Ball(Math.random()*100,Math.random()*100,Math.random()*100));
}
var animate = function(){
for(var j = arrayOfBalls.length-1; j>= 0; j--){
arrayOfBalls[j].checkBorders();
arrayOfBalls[j].checkMaxSpeed();
arrayOfBalls[j].addForce(Math.random(),Math.random());
arrayOfBalls[j].addForce(0,0.00098);
arrayOfBalls[j].display();
arrayOfBalls[j].move();
}
window.requestAnimationFrame(animate);
};
animate();
}
}
},
}
正如我在评论中提到的,问题是每个球的 display() 函数中的 clearRect() 调用。通常 canvas 只需要在动画的每个 frame/loop 中清除一次,因此 clearRect 可以放置在动画函数的顶部,如此处所示...
var animate = function(){
// Clear the canvas just once each animation frame here
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
for(var j = arrayOfBalls.length-1; j>= 0; j--) {
arrayOfBalls[j].checkBorders();
arrayOfBalls[j].checkMaxSpeed();
arrayOfBalls[j].addForce(Math.random(),Math.random());
arrayOfBalls[j].addForce(0,0.00098);
arrayOfBalls[j].display();
arrayOfBalls[j].move();
}
window.requestAnimationFrame(animate);
};