Javascript: 不能表示正弦图
Javascript: can't represent sinusoidal graph
我想制作一个正弦曲线图移动的盒子。
在我现在所处的位置,我根本无法将框表示为 canvas。一开始我能,但在计算出三角函数部分后,盒子消失了,没有错误...
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<canvas id="canvas" width="600" height="300" style="background-color:red"></canvas>
<script type="text/javascript">
var canvas = document.querySelector("canvas");//isoute me document.getElementsByTagName()
var ctx = canvas.getContext("2d");
var can_width = canvas.width;
var can_height = canvas.height;
var x,y;
function PVector(x_,y_){
var y = [];
var x = [0, Math.PI/6, Math.PI/4, Math.PI/3, Math.PI/2, 2/3*Math.PI, 3/4*Math.PI,
5/6*Math.PI, Math.PI, 7/6*Math.PI, 5/4*Math.PI, 4/3*Math.PI, 3/2*Math.PI,
5/3*Math.PI, 7/4*Math.PI, 11/6*Math.PI, 2*Math.PI];
for (var i=0, len=x["length"]; i<len; i++){
var A;
A = Math.sin(x[i]);
y.push(A);
}console.log(y);console.log(x);
return{
x:x,
y:y
};
}
var Point = {
location : {x:0, y: can_height/2},//initial location
velocity : new PVector(x,y),
display : ctx.fillRect(can_width/2,can_height/2 , 25, 25),//initial position of the box
step : function(){
this.location.x += this.velocity.x;
this.location.y += this.velocity.y;
},
display : function(){
ctx.fillRect(this.location.x, this.location.y, 25, 25);
}
};
function update(){
Point["step"]();
ctx.clearRect(0,0, can_width, can_height);
Point["display"]();
window.setTimeout(update, 1000/30);
}
function init(){
update();
}
init();
</script>
</body>
问题
在您的 PVector
对象中,您为 x
和 y
返回 Array
s,而您将它们用作 值 在 step()
方法中。这将导致整个数组作为字符串添加。
解决方案
您需要遍历该数组的东西。这是一个例子,它可能不是你想要的结果,但它显示了你需要应用的原则:
// first note the return type here:
function PVector(x_,y_){
var y = [];
var x = [0, Math.PI/6, Math.PI/4, Math.PI/3, Math.PI/2, 2/3*Math.PI,
...snipped---
return {
x:x, // x and y are arrays
y:y
};
}
var Point = {
location: {
x: 0,
y: can_height / 2,
step: 0 // some counter to keep track of array position
}, //initial location
velocity: new PVector(x, y),
step: function () {
this.location.step++; // increase step for arrays
// using modulo will keep the step as a valid value within the array length:
// if step = 7 and length = 5, index will become 2 (sort of "wrap around")
var indexX = this.location.step % this.velocity.x.length;
var indexY = this.location.step % this.velocity.y.length
this.location.x += this.velocity.x[indexX];
this.location.y += this.velocity.y[indexY];
},
...
提示:我会像 Robin 在他的回答中一样,建议简化正弦计算。当需要性能并且浏览器跟不上(即,将有数千个对象)时,正弦表很好,但在更简单的场景中,直接计算也可以。
如果您的目标只是让一个盒子在正弦曲线图中移动,可以做得更简单。
This jsfiddle 显示了一个在正弦图中移动的盒子的稍微简单的示例,我只是删除了部分代码并使用 [=22= 计算路径] 并使用时间代替 x 的预先计算值。
function update(){
time += 0.1;
ctx.clearRect(0,0, can_width, can_height);
x = time;
y = (can_height/2)+(can_height/2)*Math.sin(time);
console.log(x, y);
ctx.fillRect(x*16, y, 25, 25);
window.setTimeout(update, 1000/30);
}
变量已修改,使其在 canvas 上看起来正常。您可以编辑时间的加法,以及 y 的高度和基线,以满足您的需要。
如果您需要遵循代码中的规范,请查看 Ken 的回答。
既然你想要一个正弦曲线运动,那么使用... sin 函数是有意义的。
正弦移动的公式是:
y = maxValue * sin ( 2 * PI * frequency * time ) ;
其中频率以赫兹 (== 'number of times per second') 为单位,时间以秒为单位。
您很可能会使用 Date.now()
,因此您需要转换毫秒时间。由于 PI 的值在不久的将来应该不会改变,因此您可以计算一次幻数
k = 2 * PI / 1000 = 0.006283185307179587
公式变为:
y = sin( k * frequency * Date.now() );
下面是一个关于如何使用公式的简单示例:
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
var can_width = canvas.width;
var can_height = canvas.height;
// magic number
var k = 0.006283185307179587;
// oscillations per second
var frequency = 1/5;
// ...
var amplitude = can_width / 8;
function animate() {
ctx.clearRect(0,0,can_width, can_height);
ctx.fillStyle= '#000';
var y = amplitude * Math.sin ( k * frequency * Date.now() );
ctx.fillRect(can_width/2, can_height/2 + y, 20, 20 );
}
setInterval(animate, 30);
<canvas id="canvas" width="400" height="200" style="background-color:red"></canvas>
我想制作一个正弦曲线图移动的盒子。 在我现在所处的位置,我根本无法将框表示为 canvas。一开始我能,但在计算出三角函数部分后,盒子消失了,没有错误...
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<canvas id="canvas" width="600" height="300" style="background-color:red"></canvas>
<script type="text/javascript">
var canvas = document.querySelector("canvas");//isoute me document.getElementsByTagName()
var ctx = canvas.getContext("2d");
var can_width = canvas.width;
var can_height = canvas.height;
var x,y;
function PVector(x_,y_){
var y = [];
var x = [0, Math.PI/6, Math.PI/4, Math.PI/3, Math.PI/2, 2/3*Math.PI, 3/4*Math.PI,
5/6*Math.PI, Math.PI, 7/6*Math.PI, 5/4*Math.PI, 4/3*Math.PI, 3/2*Math.PI,
5/3*Math.PI, 7/4*Math.PI, 11/6*Math.PI, 2*Math.PI];
for (var i=0, len=x["length"]; i<len; i++){
var A;
A = Math.sin(x[i]);
y.push(A);
}console.log(y);console.log(x);
return{
x:x,
y:y
};
}
var Point = {
location : {x:0, y: can_height/2},//initial location
velocity : new PVector(x,y),
display : ctx.fillRect(can_width/2,can_height/2 , 25, 25),//initial position of the box
step : function(){
this.location.x += this.velocity.x;
this.location.y += this.velocity.y;
},
display : function(){
ctx.fillRect(this.location.x, this.location.y, 25, 25);
}
};
function update(){
Point["step"]();
ctx.clearRect(0,0, can_width, can_height);
Point["display"]();
window.setTimeout(update, 1000/30);
}
function init(){
update();
}
init();
</script>
</body>
问题
在您的 PVector
对象中,您为 x
和 y
返回 Array
s,而您将它们用作 值 在 step()
方法中。这将导致整个数组作为字符串添加。
解决方案
您需要遍历该数组的东西。这是一个例子,它可能不是你想要的结果,但它显示了你需要应用的原则:
// first note the return type here:
function PVector(x_,y_){
var y = [];
var x = [0, Math.PI/6, Math.PI/4, Math.PI/3, Math.PI/2, 2/3*Math.PI,
...snipped---
return {
x:x, // x and y are arrays
y:y
};
}
var Point = {
location: {
x: 0,
y: can_height / 2,
step: 0 // some counter to keep track of array position
}, //initial location
velocity: new PVector(x, y),
step: function () {
this.location.step++; // increase step for arrays
// using modulo will keep the step as a valid value within the array length:
// if step = 7 and length = 5, index will become 2 (sort of "wrap around")
var indexX = this.location.step % this.velocity.x.length;
var indexY = this.location.step % this.velocity.y.length
this.location.x += this.velocity.x[indexX];
this.location.y += this.velocity.y[indexY];
},
...
提示:我会像 Robin 在他的回答中一样,建议简化正弦计算。当需要性能并且浏览器跟不上(即,将有数千个对象)时,正弦表很好,但在更简单的场景中,直接计算也可以。
如果您的目标只是让一个盒子在正弦曲线图中移动,可以做得更简单。
This jsfiddle 显示了一个在正弦图中移动的盒子的稍微简单的示例,我只是删除了部分代码并使用 [=22= 计算路径] 并使用时间代替 x 的预先计算值。
function update(){
time += 0.1;
ctx.clearRect(0,0, can_width, can_height);
x = time;
y = (can_height/2)+(can_height/2)*Math.sin(time);
console.log(x, y);
ctx.fillRect(x*16, y, 25, 25);
window.setTimeout(update, 1000/30);
}
变量已修改,使其在 canvas 上看起来正常。您可以编辑时间的加法,以及 y 的高度和基线,以满足您的需要。
如果您需要遵循代码中的规范,请查看 Ken 的回答。
既然你想要一个正弦曲线运动,那么使用... sin 函数是有意义的。
正弦移动的公式是:
y = maxValue * sin ( 2 * PI * frequency * time ) ;
其中频率以赫兹 (== 'number of times per second') 为单位,时间以秒为单位。
您很可能会使用 Date.now()
,因此您需要转换毫秒时间。由于 PI 的值在不久的将来应该不会改变,因此您可以计算一次幻数
k = 2 * PI / 1000 = 0.006283185307179587
公式变为:
y = sin( k * frequency * Date.now() );
下面是一个关于如何使用公式的简单示例:
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
var can_width = canvas.width;
var can_height = canvas.height;
// magic number
var k = 0.006283185307179587;
// oscillations per second
var frequency = 1/5;
// ...
var amplitude = can_width / 8;
function animate() {
ctx.clearRect(0,0,can_width, can_height);
ctx.fillStyle= '#000';
var y = amplitude * Math.sin ( k * frequency * Date.now() );
ctx.fillRect(can_width/2, can_height/2 + y, 20, 20 );
}
setInterval(animate, 30);
<canvas id="canvas" width="400" height="200" style="background-color:red"></canvas>