[英]Make oscillations smoothly increase/decrease when frequency being changed dynamically
I'm modeling the resonance effect with html5 canvas to animate spring when its reach the resonance.我正在使用 html5 画布对共振效果进行建模,以在弹簧达到共振时为其设置动画。 Also got jquery ui slider (max ranged) that changes frequency (w) of the oscillations dynamically during the animation.
还获得了 jquery ui 滑块(最大范围),可在动画期间动态更改振荡的频率 (w)。 The problem is when its changed, for some reason sine wave brokes at some points and the animation is not smooth.
问题是当它改变时,由于某种原因正弦波在某些点中断并且动画不流畅。 This is only happens when changing frequency, with amplitude its much better.
这仅在改变频率时发生,幅度更好。 my main function to render each frame is this:
我渲染每一帧的主要功能是这样的:
function doSways() {
var spring = springs[0],
a = 0,
A = params.standParams.A,
w = params.standParams.w;
animIntervalId = setInterval(function() {
ctx.clearRect(0, 0, cnvW, cnvH);
A = params.standParams.A;
w = params.standParams.w;
/*if (w < params.standParams.w) { // with this expression and commented <w = params.standParams.w> it works a bit smoother but still some issues can be noticed, for example sharp increases just after the new change of the frequency (w) on the slider
w += 0.01;
}*/
stand.y = A*Math.sin(a*degToRad*w) + offsetY;
stand.draw();
spring.draw(stand.y, A, w);
if (a++ >= 360) { // avoid overflow
a = 0;
}
},
25);
}
here's how I change frequency(w) on the slider and assign it to params.standParams.w这是我如何更改滑块上的频率(w)并将其分配给 params.standParams.w
$( "#standfreq_slider" ).slider({
range: "max",
min: 1,
max: 25,
step: 1,
value: 5,
slide: function( event, ui ) {
params.standParams.w = parseInt(ui.value);
}
});
);
That if expression in doSways function kinda work but it casues another problem, I need to know the direction of sliding to determine wether I need to += or -= 0.01.. How to make everything work ideal ?如果 doSways 函数中的表达式有点工作,但它会导致另一个问题,我需要知道滑动的方向来确定我需要 += 或 -= 0.01 .. 如何使一切工作理想?
based on the basic formula for sinusoids:基于正弦曲线的基本公式:
V = V0 + A * sin(2 * pi * f * t + phi)
Where:在哪里:
We want the current value (V) to be the same before and after a frequency change.我们希望电流值 (V) 在频率变化前后保持相同。 In order to do that we will need a frequency (f) and phase (phi) before and after the change.
为此,我们需要更改前后的频率 (f) 和相位 (phi)。
First we can set the first equation equal the the second one:首先,我们可以设置第一个等式等于第二个:
V0 + A * sin(2 * pi * f1 * t + phi1) = V0 + A * sin(2 * pi * f2 * t + phi2)
do some cancelling:做一些取消:
2 * pi * f1 * t + phi1 = 2 * pi * f2 * t + phi2
solve for the new phase for the final formula:求解最终公式的新相:
phi2 = 2 * pi * t * (f1 - f2) + phi1
More mathy version:更多数学版本:
edited:编辑:
check out modified fiddle: https://jsfiddle.net/potterjm/qy1s8395/1/查看修改后的小提琴: https : //jsfiddle.net/potterjm/qy1s8395/1/
Well the pattern i explain below is one i use quite often.我在下面解释的模式是我经常使用的模式。
( It might very well have a name - please SO people let me know if so-. ) (它很可能有一个名字 - 如果是这样的话,请让人们告诉我。)
Here's the idea : whenever you need to want a property evolving in a smooth manner, you must distinguish the target value, and the current value.这里的想法是:每当你需要一个属性以平滑的方式演化时,你必须区分目标值和当前值。 If, for some reason, the target value changes, it will only affect the current value in the way you decided.
如果由于某种原因,目标值发生变化,它只会以您决定的方式影响当前值。
To get from the current value to the target value, you have many ways :要从当前值到目标值,您有很多方法:
• most simple : just get it closer from a given ratio on every tick : • 最简单:只需在每个刻度上从给定的比率接近:
current += ratio * (target-current);
where ratio is in [0, 1], 0.1 might be ok.其中比率在 [0, 1] 中,0.1 可能没问题。 You see that, with ratio == 1, current == target on first tick.
您会看到,第一次刻度上的比率 == 1,当前 == 目标。
Beware that this solution is frame-rate dependent, and that you might want to threshold the value to get the very same value at some point, expl :请注意,此解决方案取决于帧速率,并且您可能希望对该值设置阈值以在某些时候获得完全相同的值,expl:
var threshold = 0.01 ;
if (Math.abs(target-current)<threshold) current = target;
• You can also reach target at a given speed : • 您还可以以给定的速度到达目标:
var sign = (target - current) > 0 ? 1 : -1;
current += sign * speedToReachTarget * dt;
Now we are not frame-rate dependent (you must handle frame time properly), but you will have 'bouncing' if you don't apply a min/max and a threshold also :现在我们不依赖于帧速率(您必须正确处理帧时间),但是如果您不应用最小值/最大值和阈值,则会出现“弹跳”:
if (Math.abs(target-current)<0.01) {
current = target;
return;
}
var sign = (target - current) > 0 ? 1 : -1;
current += sign * speedToReachTarget * dt;
current = (( sign > 0) ? Math.min : Math.max )( target, current);
• and you might use many other type of interpolation/easing. • 并且您可能会使用许多其他类型的插值/缓动。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.