Javascript 画布上的正弦运动:在转折点调用函数
在画布上,圆在椭圆路径上移动: 守则的有关部分:Javascript 画布上的正弦运动:在转折点调用函数,javascript,math,canvas,Javascript,Math,Canvas,在画布上,圆在椭圆路径上移动: 守则的有关部分: function step() { x = Math.sin(counter) * 10 + 100; y = Math.cos(counter) * 50 + 100; // draw Circle with x / y position counter += 0.025; window.requestAnimationFrame(step); } window.requestAnimationFr
function step() {
x = Math.sin(counter) * 10 + 100;
y = Math.cos(counter) * 50 + 100;
// draw Circle with x / y position
counter += 0.025;
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
现在我想在椭圆运动的垂直转折点调用一个函数,所以当y
处于其最高/最低值时。最好的方法是什么
我尝试将以前的y
值与当前的y
值进行比较,但结果不正确。(或仅在一个方向上。)
提前感谢您的帮助 微积分
通过取其导数并找到导数等于0
的位置,可以找到y
的局部极值(最高值和最低值)
如果你对微积分知之甚少,一种用于计算直线在任意给定点的斜率的导数,y
的导数(有时)表示为y'
,发音为“y-prime”
知道斜率有帮助的原因是,当给定点的导数为0
时,函数的瞬时斜率为0
,这意味着原始函数既不增加也不减少,因此我们必须处于局部最大值或局部最小值。(你可以通过更多的微积分魔法来了解自己是处于最小值还是最大值。)
如果这不合理,想象你正在爬山。当你向上走的时候,坡度是正的。一旦到达顶部,坡度为0
,因为您不会上下斜坡。在两座山之间行走也是一样——一旦你到达山谷,那里所有东西都是平坦的(0
slope),你就到了谷底
所以。。。如果你想学习如何求导数,请查看。否则,快速的答案是Math.cos(counter)*50+100的导数是-50*Math.sin(counter)
。从这里开始,你需要做的就是找到这个导数的位置0
,它每n*180
度或n*Math.PI
弧度发生一次,以你使用的为准
快速回答
无论何时计数器%180==0
都需要调用函数
然而,问题是,计数器
变量递增的时间间隔永远不会等于Math.PI
,因此永远不会得到精确的0
斜率。我建议将您的时间间隔切换到接近您拥有的时间间隔,但将平均分为3.14159..
,如0.008*Math.PI
(大约为.02513,但您可以根据需要进行微调):
var canvas=document.querySelector('canvas'),
ctx=canvas.getContext('2d'),
w=画布宽度,
h=画布高度,
x=y=0;
计数器=0;
函数步骤(){
如果(计数器Math.PI*2){
var maxY=数学最大值(数学cos(计数器)*50+100,数学cos(计数器+0.025)*50+100);
console.log(“maxY:+maxY”);
}
如果(计数器Math.PI){
var minY=数学最小值(数学cos(计数器)*50+100,数学cos(计数器+0.025)*50+100);
console.log(“minY:+minY”);
}
x=数学sin(计数器)*10+100;
y=数学cos(计数器)*50+100;
ctx.clearRect(0,0,w,h);
ctx.save();
ctx.beginPath();
弧(x,y,4,0,2*Math.PI,false);
ctx.fill();
ctx.restore();
计数器+=0.025;
如果(计数器>数学PI*2){
计数器%=数学PI*2;
}
window.requestAnimationFrame(步骤);
}
window.requestAnimationFrame(步骤);
这是。我想这正是您所要求的。在处理浮点值时,您需要检查角度是否有一定的公差,因为由于舍入误差,您可能永远无法获得精确的值进行比较
我建议采取以下办法:
- 使用步长值(如您所做)
- 定义顶部和底部角度
- 定义公差=步骤/2
例如:
var step = 0.025, // angle step
bottom = 0.5 * Math.PI, // bottom angle (=90 deg)
top = 1.5 * Math.PI, // top angle (=270 deg)
tol = step * 0.5; // tolerance, 50% of step
现在,您可以通过以下方式比较该角度和公差:
if (counter > bottom - tol && counter < bottom + tol) {...bottom...}
else if (counter > top - tol && counter < top + tol) {...top...};
还有几件事:
- 你已经切换了cos/sin。Cos代表x,sin代表y,否则它会朝相反的方向发展
- var x=y=0不会做您认为它会做的事情,这里不会声明y
不需要太多数学知识,你可以做的一件事就是始终计算上一个y
的值,然后当方向改变时,更改标志的值以帮助你确定每种情况,基本上是这样的:
var canvas = document.querySelector('canvas'),
ctx = canvas.getContext('2d'),
w = canvas.width,
h = canvas.height,
x = y = prev_y = 0;
counter = 0;
flag = 1;
function step() {
x = Math.sin(counter) * 10 + 100;
y = Math.cos(counter) * 50 + 100;
if(prev_y > y && flag == 1){
//Function for lowest position goes here
flag = 0;
}
if(prev_y < y && flag == 0){
//Function for highest position goes here
flag = 1;
}
ctx.clearRect(0, 0, w, h);
ctx.save();
ctx.beginPath();
ctx.arc(x, y, 4, 0, 2*Math.PI, false);
ctx.fill();
ctx.restore();
counter += 0.025;
window.requestAnimationFrame(step);
prev_y = y;
}
window.requestAnimationFrame(step);
var canvas=document.querySelector('canvas'),
ctx=canvas.getContext('2d'),
w=画布宽度,
h=画布高度,
x=y=prev_y=0;
计数器=0;
flag=1;
函数步骤(){
x=数学sin(计数器)*10+100;
y=数学cos(计数器)*50+100;
如果(上一个y>y&&flag==1){
//最低位置的函数在这里
flag=0;
}
如果(上一个y
或者,可能更简单,不要寻找导数sin(计数器)==0的确切位置,因为使用浮点数学,几乎永远不会达到该精确值。相反,只需寻找sin(counter)
符号改变的点。幸运的是,您已经为另一个轴计算了sin(counter)
,因此这不需要花费任何成本。甚至,您可以进行浮点舍入,但我同意,这总是有可能无法捕捉到所有的0。舍入还可能会多次调用“hit zero”函数,如果d
if (counter > bottom - tol && counter < bottom + tol) {...bottom...}
else if (counter > top - tol && counter < top + tol) {...top...};
counter = counter % (2 * Math.PI);
var canvas = document.querySelector('canvas'),
ctx = canvas.getContext('2d'),
w = canvas.width,
h = canvas.height,
x = y = prev_y = 0;
counter = 0;
flag = 1;
function step() {
x = Math.sin(counter) * 10 + 100;
y = Math.cos(counter) * 50 + 100;
if(prev_y > y && flag == 1){
//Function for lowest position goes here
flag = 0;
}
if(prev_y < y && flag == 0){
//Function for highest position goes here
flag = 1;
}
ctx.clearRect(0, 0, w, h);
ctx.save();
ctx.beginPath();
ctx.arc(x, y, 4, 0, 2*Math.PI, false);
ctx.fill();
ctx.restore();
counter += 0.025;
window.requestAnimationFrame(step);
prev_y = y;
}
window.requestAnimationFrame(step);