簡體   English   中英

畫布擺動畫-畫布翻譯

[英]canvas pendulum animation - canvas translating

我正在嘗試在HTML5 Canvas中創建簡單的擺錘,但遇到了麻煩。 我想將其左右旋轉25度,因此我計算出每幀應在y軸上平移-3.5 px(向右平移3.5 px)。 我正在使用下面的代碼

var rotation = Math.PI/180, //rotate about 1deg
    translation = -3.5,
    counter = 0; //count rotations

function draw() {
    var element = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');

    ctx.clearRect(0,0,element.width,element.height);
    ctx.translate(0, translation);
    ctx.rotate(rotation);

    //function draws all objects
    objects(element,ctx);

    if (counter == 25) {
      rotation *= -1;
      translation *= -1;
      counter = -25;
    } 
    counter += 1;

    window.requestAnimationFrame(draw);
  }

一切看起來都不錯,但是當鍾擺改變方向時,所有事物也都在x軸上平移,並且幾秒鍾后從屏幕上消失。 或者也許我在計算中錯過了什么? 我的代碼在這里https://jsfiddle.net/qskxjzv9/2/

預先感謝您的回答。

問題是,當涉及旋轉,然后平移時,x和y的平移方向將與看似邏輯的方向不同。

為了解決這個問題,我們實際上不需要涉及平移,而只是使用它來放置樞軸(旋轉點),然后基於計算擺運動的另一種方式使用絕對旋轉。

例如,這將解決翻譯問題以及使擺運動平滑:

  • 更改繪制方法以繪制原點為(0,0)的擺-只需更改初始坐標即可使它們圍繞(0,0)展開
  • 平移到屏幕的樞軸點-這是旋轉的地方。
  • 使用sin()作為因子進行旋轉-這將創建一個平滑的動畫,看起來更像一個鍾擺,並且當范圍為[-1,1]時,它將限制角度移動
  • 使用counter移動sin()代替-這是一個頻率敏感的因素(您可以稍后將其轉換為實際頻率,例如使鍾擺每分鍾移動n次,等等)。 為簡單起見,我只使用了現有的counter變量並減小了其步長值。

然后,主要代碼:

var maxRot = 25 / 180 * Math.PI,    // max 25° in both directions
    counter = 0,

    // these are better off outside loop
    element = document.getElementById('canvas');
    ctx = element.getContext('2d');

function draw() {

  // reset transform using absolute transformation. Include x translation:
  ctx.setTransform(1,0,0,1,element.width*0.5,0);

  // clear screen, compensate for initial translate
  ctx.clearRect(-element.width*0.5,0,element.width,element.height);

  // rotate using sin() with max angle
  ctx.rotate(Math.sin(counter) * maxRot);

  // draw at new orientation which now is pivot point
  objects(element, ctx);

  // move sin() using "frequency"-ish value
  counter += 0.05;

  window.requestAnimationFrame(draw);
}

小提琴

額外

感謝@ Blindman67提供了其他改進:

要根據振盪來控制頻率,您可以做一些小的更改-首先定義頻率:

var FREQUENCY = 3;

定義一個將執行轉換的函數:

function sint(time) {
    return Math.sin(FREQUENCY * time * Math.PI * 0.002); // 0.002 allow time in ms
}

如果現在將draw()方法更改為采用時間參數而不是計數器:

function draw(time) {
   ...
}

然后,您可以像這樣調用輪播:

ctx.rotate(sint(time) * maxRot);

您需要將原點平移到要旋轉的點:

  ctx.translate(element.width / 2, 0);

然后,按照您的建議進行輪換:

  ctx.rotate(rotation);

最后,翻譯回:

  ctx.translate(- element.width / 2, 0);

看到您的小提琴的評論叉

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM