2015-09-17 18 views
2

我使用html5畫布爲諧振效果建模,以便在彈簧達到共振時對其進行動畫製作。 還得到了jQuery UI滑塊(最大範圍),在動畫期間動態地改變振盪的頻率(w)。問題在於它的改變,由於某種原因,正弦波在某些點上斷裂,並且動畫不平滑。這隻有在頻率變化時纔會發生,振幅變得更好。 我渲染每一幀的主要功能是:當頻率動態變化時,使振動平穩增加或減少

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); 
} 

這裏就是我的滑塊改變頻率(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); 

    } 
    }); 
); 

的是,如果doSways表達函數有點工作,但它支付另一個問題,我需要知道滑動的方向來確定我需要+ =或 - = 0.01 .. 如何使一切工作理想?

問題插圖現場 jsfiddle

+0

您是否嘗試過的+ =和 - =你自己了嗎? – SkullDev

+0

你可以在jsfiddle中模擬一個演示嗎?這樣我們可以看到/測試發生了什麼? – indubitablee

+0

@indubitablee是的當然,https://jsfiddle.net/v98jyr67/8/ – ampawd

回答

1

基於用於正弦曲線的基本公式:

V = V0 + A * sin(2 * pi * f * t + phi)

其中:

  • 五:電流值
  • V0:中心值
  • 答:振幅
  • ˚F :頻率(Hz)
  • 噸:時間(秒)
  • 披:相

我們希望的電流值(V)是相同的前和頻率改變之後。爲了做到這一點,我們需要改變前後的頻率(f)和相位(phi)。

首先我們可以通過設置第一方程等於第二個:

V0 + A * sin(2 * pi * f1 * t + phi1) = V0 + A * sin(2 * pi * f2 * t + phi2)

做一些抵消:

2 * pi * f1 * t + phi1 = 2 * pi * f2 * t + phi2

解決用於最終公式新相:

phi2 = 2 * pi * t * (f1 - f2) + phi1

更多mathy版本:

final formula

編輯:

退房修改小提琴:https://jsfiddle.net/potterjm/qy1s8395/1/

+0

你如何從'V0 + A * sin(2 * pi * f1 * t + phi1)= V0 + A * sin(2 * pi * f2 * t + phi2)'??? – ampawd

+0

在我說的「做一些取消」的步驟中:首先從兩側減去V0(這會去掉V0)。然後用A分開兩邊,然後反兩邊。你留下的是'* 2 * pi * f1 * t + phi1 = 2 * pi * f2 * t + phi2' – Potter

+0

在你的情況下,因爲你使用歐米茄的頻率,它會以'phi2 = w1-w2)* t + phi1'。我昨天遇到了這個問題,並且完美地工作。 – Potter

0

嗯,我在下面解釋的圖案是一個我經常使用。
(這很可能會擁有一個名字 - 請這樣的人讓我知道如果所謂。)

這裏的想法:每當你需要想一個屬性以平穩的方式發展的,必須區分目標值和當前值值。如果由於某種原因,目標的值發生了變化,它將僅以您決定的方式影響值目前值。

要從當前值與目標值得到的,你有很多方法:

•最簡單:只需把它從一個給定的比例接近每滴答:

current += ratio * (target-current); 

哪裏比在[0,1]中,0.1可能沒問題。你看,比例== 1,當前==目標在第一次打勾。
要注意的是這種解決方案是幀速率有關,那你可能需要的閾值,以獲得在某些時候非常相同的值,EXPL:

var threshold = 0.01 ; 
if (Math.abs(target-current)<threshold) current = target; 

•您還可以在給定的速度達到目標:

var sign = (target - current) > 0 ? 1 : -1; 
current += sign * speedToReachTarget * dt; 

現在我們不再幀速率取決於(你必須妥善處理幀時間),但你將有「彈跳」,如果你不申請一個最小值/最大值和閾值也:

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); 

•您可能會使用許多其他類型的插值/緩動。