繁体   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