在画布上,圆圈在椭圆路径上移动:http://jsfiddle.net/NwwsP/
代码的相关部分:
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 :(得分:1)
var canvas = document.querySelector('canvas'),
ctx = canvas.getContext('2d'),
w = canvas.width,
h = canvas.height,
x = y = 0;
counter = 0;
function step() {
if (counter < Math.PI*2 && counter+0.025 > Math.PI*2) {
var maxY = Math.max(Math.cos(counter)*50+100, Math.cos(counter+0.025)*50+100);
console.log("Max Y: " + maxY);
}
if (counter < Math.PI && counter+0.025 > Math.PI) {
var minY = Math.min(Math.cos(counter)*50+100, Math.cos(counter+0.025)*50+100);
console.log("Min Y: " + minY);
}
x = Math.sin(counter) * 10 + 100;
y = Math.cos(counter) * 50 + 100;
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;
if (counter > Math.PI*2) {
counter %= Math.PI*2;
}
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
这是my solution。我想这就是你的要求。
答案 1 :(得分:1)
你可以做的事情没有太多的数学,总是计算前一个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);
<强> JSFiddle Demo 强>
答案 2 :(得分:0)
积分!
您可以通过获取y
的导数并找到该导数等于0
的位置来找到y
的局部极值(最高值和最低值)。
如果您对微积分了解不多,则用于计算任意给定点的线斜率的导数,y'
的导数(有时)表示为0
,发音为&#34; y-prime。&#34;
知道斜率有用的原因是因为当给定点的导数为0
时,函数的瞬时斜率为0
,这意味着< em>原始函数既不增加也不减少,因此我们必须处于局部最大值或局部最小值。 (你可以通过更多的微积分魔法来判断你是在最小值还是最大值。)
如果这没有意义,想象一下你爬山了。当你走路时,坡度是正的。一旦到达顶部,斜率为0
,因为您没有上坡或下坡。在两座山间行走也是如此 - 一旦你到达一切平坦的山谷(Math.cos(counter) * 50 + 100
斜坡),你就会在底部。
所以......如果你想学习 如何获取衍生物,请查看this link。否则,快速回答是-50 * Math.sin(counter)
的导数是0
。你需要做的就是找到这个导数n * 180
的位置,它发生在每n * Math.PI
度,或counter % 180 === 0
弧度,无论你使用哪个。
快速回答
您需要在counter
时调用您的函数。
但问题是,Math.PI
变量递增的时间间隔将永远不会等于0
,因此您永远不会得到精确的{{1}的斜率}。我建议您将时间间隔转换为接近您所拥有的时间间隔,但会平均分配到3.14159..
,例如0.008 * Math.PI
(大约为.02513,但您可以对此进行微调)想):
counter += 0.008 * Math.PI;
答案 3 :(得分:0)
当您处理浮点值时,您需要检查角度是否有一些容差,因为舍入错误可能永远无法获得与之比较的精确值。
我建议采用以下方法:
示例:
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...};
通过将计数器限制为360°,确保计数器不会超过一个回合:
counter = counter % (2 * Math.PI);
<强> FIDDLE 强>
其他一些事情: