簡體   English   中英

如何讓我的HTML畫布點更自然地移動?

[英]How can i make my HTML canvas dots move more naturally?

鏈接到我的代碼筆在這里

我想知道如何讓畫布點以更流暢,更液體的方式移動。

我已經嘗試限制一定數量的渲染(draw())的方向,這已經改善了一點! 但它仍然缺乏流動性,只是僵硬和“硬編碼”。

此switch語句是方向設置的方式,可以傳遞隨機整數或前一個方向。

 switch (direction) {
                    case 1:
                      star.x--;
                      break;
                    case 2:
                      star.x++;
                      break;
                    case 3:
                      star.y--;
                      break;
                    case 4:
                      star.y++;
                      break;
                    case 5:
                      star.y--;
                      star.x--;
                      break;
                    case 6:
                      star.y--;
                      star.x++;
                      break;
                    case 7:
                      star.y++;
                      star.x++;
                      break;
                    case 8:
                      star.y++;
                      star.x--;
                      break;
}

謝謝!

你可以這樣做:

  • 基於隨機線點生成基數樣條
  • 沿着那條線走,並在當前位置上繪制一顆星

為什么選擇基數樣條? 基數樣條曲線將在一組點之間生成平滑線。 如果還有張力值。 通過誇大張力值(即在正常[0,1]范圍之外),它將產生卷曲的線條。

快照

// draw example lines
var ctx = c.getContext("2d"), p = [0,100, 25,40, 50,70, 75,50, 100,80, 125,32, 150,100, 175,60];
ctx.font = "bold 16px sans-serif";

render(0); render(0.5); render(-2);
ctx.setTransform(1,0,0,1,0, 110);

render(-2, 3, "Segments: 3"); render(-2, 9, "Segments: 9"); render(-2, 25, "Segments: 25");

function render(t, seg, txt) {
  ctx.beginPath();
  ctx.moveTo(0, 100);
  ctx.curve(p, t, seg || 20);
  ctx.stroke();
  ctx.fillText(txt ? txt : (!t ? "Plain poly-line" : "Cardinal, tension: " + t), 0, 20);
  ctx.translate(200,0);
}

我們可以利用這個屬性並沿着這樣的線繪制一個點以產生液體運動。 可以通過降低/增加樣條中每條線之間的分段分辨率來改進運動,這將影響平滑度和速度。

其他優點是我們不必在動畫本身中計算任何東西(在設置點(緩存)時會有一個初始的“峰值”),我們只是更新數組指針並渲染。 並且分布將是相當均勻的,因為點是沿着稍微均勻分布(不可見)路徑的力。

如何實現它可以改變當然 - 這是一個方法的一個例子:

示例實現

定義一個星形對象(它應該是原型,但為了演示):

function Star(ctx, xseg) {

    var points = [],              // holds points for cardinal points
        cPos = 0, oPos = -1,      // positions in line
        len,
        w = ctx.canvas.width,
        x = -10, y = -10;

    // this iterates and loop the point list            
    this.animate = function() {
        cPos++;

        if (cPos > len - 2) {
            cPos = 0; oPos = -1;
        }

        var pos = cPos * 2;
        x = points[pos];
        y = points[pos + 1];

        drawStar();
    }

    // render some star
    function drawStar() {
        ctx.rect(x, y, 2, 2);
    }

    // This generate a set of random points, then converts those into
    // points for a cardinal spline (linked as script).
    function generatePath() {
        var w = ctx.canvas.width,
            h = ctx.canvas.height,
            numOfSeg = 20,
            dh = h / numOfSeg,
            i= 0, l, x, y;

        for(; i<= numOfSeg; i++) {          
            x = xseg + w / 8 * Math.random();
            y = h - (i * dh + ((dh / 2) * Math.random() - (dh / 4)));
            points.push(x, y);
        }

        points = curve(points, -2, 200 * Math.random() + 100);
        l = points.length;

        // adjust for out of edges
        for(i = 0; i < l; i += 2) if (points[i] > w) points[i] -= w;
        len = points.length / 2;
        cPos = parseInt(len * Math.random());
    }   
    generatePath();
}

完整的例子

function Star(ctx, xseg) {

  var points = [],              // holds points for cardinal points
      cPos = 0, oPos = -1,      // positions in line
      len,
      w = ctx.canvas.width,
      x = -10, y = -10;

  this.animate = function() {
    cPos++;
    if (cPos > len - 2) {
      cPos = 0;  oPos = -1;
    }

    var pos = cPos * 2;
    x = points[pos];
    y = points[pos + 1];

    drawStar();
  };

  function drawStar() {
    ctx.moveTo(x + 2, y);
    ctx.arc(x, y, 2, 0, Math.PI*2);
  }

  function generatePath() {
    var w = ctx.canvas.width,
        h = ctx.canvas.height,
        numOfSeg = 20,
        dh = h / numOfSeg,
        i= 0, l, x, y;

    for(; i <= numOfSeg; i++) {         
      x = xseg + w / 8 * Math.random();
      y = h - (i * dh + ((dh / 2) * Math.random() - (dh / 4)));
      points.push(x, y);
    }

    points = getCurvePoints(points, -2, (400 * Math.random() + 200)|0);
    l = points.length;

    for(i = 0; i < l; i += 2) if (points[i] > w) points[i] -= w;
    len = points.length / 2;
    cPos = (len * Math.random())|0;

  }
  generatePath();
}

// Main code
var canvas = document.querySelector("canvas"),
    ctx = canvas.getContext("2d"),
    stars = [],
    numOfStars = 100,
    segs = canvas.width / numOfStars, 
    i = 0,
    throttle = 0,
    delay = 2;

// create stars
for(; i < numOfStars; i++) stars.push(new Star(ctx, i * segs - segs));

ctx.fillStyle = "#fff";
ctx.shadowColor ="#fff";
ctx.shadowBlur = 7;

// ANIMATE
(function animate() {      
  if (!throttle) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.beginPath();
    for(var i = 0; i < stars.length; i++) stars[i].animate();
    ctx.fill(); 
  }

  throttle++;
  if (throttle === delay) throttle = 0;

  requestAnimationFrame(animate);
})();

請參閱此答案中的基數樣條實現的代碼。

另一種方法是使用粒子並使用例如正弦函數來變化速度。 為了使其最佳地工作,您可能需要使用速度網格來影響基於位置的粒子。 網格可以具有隨機方向和速度。

暫無
暫無

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

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