【问题标题】:Canvas JS - how to do random movement with accelerationCanvas JS - 如何通过加速度进行随机运动
【发布时间】:2018-12-07 15:06:58
【问题描述】:

我正在为这个特殊的任务而苦苦挣扎。我想用某种加速度制作随机移动的粒子动画(我知道它不可能那么随机)。我发现一个网站正在使用这种效果,但我自己无法复制它,我花了好几个小时研究解决方案,但没有成功。

这个site 具有预期的效果。我不知道如何一遍又一遍地重复运动和加速。

有一瞬间我以为我知道它是用 pixijs 制作的,但我也没有设法在 pixi 中做到这一点。我所能做的只是随机生成圆周运动,但看起来不太好。

如果有人能把我推向正确的方向,我真的很感激。

编辑: Here 是我目前得到的,正如我所说,它只使用圆周运动。

这只是我的 JS 文件:

function getRandomInt(min, max) {

min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function getLineWidth(max, min, distance) {
  if(distance < min) {return 1;}
  if(distance >= min && distance <= max) {
    return -(distance - max) / min;
  } else {
    return 0;
  }
}

function particles(numberOfParticles) {
  var canvas = document.getElementById('canvas'),
      ctx = canvas.getContext('2d');

  var W = canvas.width;
  var H = canvas.height;

  var x = 0, y = 0;

  //random properties of particle
  var particleProperties = [];
  for(i = 0; i < numberOfParticles; i++) {
    var speed = Math.random() * (0.35 - 0.1) + 0.1; //0.1 - 0.35
    var radius = getRandomInt(100, 500); // 100 - 500
    var angle = 0;
    var direction = Math.random() < 0.5 ? -1 : 1;
    var circleCenterX = getRandomInt(250, 550); //250 - 550
    var circleCenterY = getRandomInt(150, 550); //150 - 550
    var sizeOfParticle = getRandomInt(1, 3);

    particleProperties[i] = [speed, radius, angle, direction, circleCenterX, circleCenterY, sizeOfParticle];
  }

  function draw() {
      ctx.clearRect(0, 0, W, H);

      var coordinatesOfParticles = [];
      //object R
      for(i = 0; i < numberOfParticles; i++) {
          var newX = particleProperties[i][1] * Math.cos(particleProperties[i][2] * (Math.PI/180) * particleProperties[i][3]);
          var newY = particleProperties[i][1] * Math.sin(particleProperties[i][2] * (Math.PI/180) * particleProperties[i][3]);
          x = newX + particleProperties[i][4];
          y = newY + particleProperties[i][5];
          ctx.beginPath();
          ctx.arc(x, y, particleProperties[i][6], 0, 2*Math.PI);
          ctx.fillStyle = 'black';
          ctx.fill();
          ctx.stroke();
          particleProperties[i][2] += particleProperties[i][0];
          coordinatesOfParticles[i] = [x, y];
      }

      for(i = 0; i < coordinatesOfParticles.length - 1; i++) {
          for(j = i + 1; j < coordinatesOfParticles.length; j++) {
              if(math.distance(coordinatesOfParticles[i], coordinatesOfParticles[j]) < 220) {
                  ctx.beginPath();
                  ctx.lineWidth = getLineWidth(220, 90, math.distance(coordinatesOfParticles[i], coordinatesOfParticles[j]));
                  ctx.moveTo(coordinatesOfParticles[i][0], coordinatesOfParticles[i][1]);
                  ctx.lineTo(coordinatesOfParticles[j][0], coordinatesOfParticles[j][1]);
                  ctx.stroke();
              }
          }
      }
  }

  setInterval(draw, 1000/60);
}

【问题讨论】:

  • 我很肯定这个网站使用这个库:vincentgarreau.com/particles.js 查看他们的代码 GitHub github.com/VincentGarreau/particles.js
  • @COLBYBROOKS 我知道这个网站,但这不是我要找的。我实际上可以像网站一样做到这一点,但我需要运动和加速方面的帮助。老实说,大多数人都在运动。 particles.js 只是直线运动,这不是我想要做的,无论如何谢谢你的回答。
  • 一种方法是将粒子的speedMath.sin(something) 相乘,其中something 可能是帧数的函数,例如framesNumber * Math.PI / 180。请添加一些代码。
  • @enxaneta 我添加了代码,也许你会知道怎么做或者我做错了

标签: javascript canvas random pixi.js


【解决方案1】:

我想我为我的问题找到了解决方案,即使它看起来不像我提到的网站那么好,但它可以达到目的。这是我编辑的particles.js 文件。也许它会对某人有所帮助。

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function getLineWidth(max, min, distance) {
  if(distance < min) return 1;
  if(distance >= min && distance <= max) {
    return -(distance - max) / min;
  } else {
    return 0;
  }
}

function particles(numberOfParticles) {
  var canvas = document.getElementById('canvas'),
      ctx = canvas.getContext('2d');

  var W = canvas.width;
  var H = canvas.height;

  var x = 0, y = 0;

  //random object
  var particleProperties = [];
  for(i = 0; i < numberOfParticles; i++) {
    var speed = Math.random() * (0.30 - 0.18) + 0.18; //0.1 - 0.35
    var radius = getRandomInt(100, 200); // 100 - 500
    var angle = 0;
    var direction = Math.random() < 0.5 ? -1 : 1;
    var circleCenterX = 400; //250 - 550
    var circleCenterY = getRandomInt(100, 600); //150 - 550
    var sizeOfParticle = getRandomInt(1, 3);
    var X = getRandomInt(30, 230);
    var Y = getRandomInt(290, 360);

    particleProperties[i] = [speed, radius, angle, direction, circleCenterX, circleCenterY, sizeOfParticle, X, Y];
  }

  function draw() {
      //clear rect
      ctx.clearRect(0, 0, W, H);

      var coordinatesOfParticles = [];
      //objekt R
      for(i = 0; i < numberOfParticles; i++) {
          var newX = particleProperties[i][1] * Math.cos(particleProperties[i][2] * (Math.PI/particleProperties[i][7]) * particleProperties[i][3]);
          var newY = particleProperties[i][1] * Math.tan(particleProperties[i][2] * (Math.PI/particleProperties[i][8]) * particleProperties[i][3]);
          x = newX + particleProperties[i][4];
          y = newY + particleProperties[i][5];
          ctx.beginPath();
          ctx.arc(x, y, particleProperties[i][6], 0, 2*Math.PI);
          ctx.fillStyle = 'grey';
          ctx.fill();
          ctx.stroke();
          particleProperties[i][2] += particleProperties[i][0];
          coordinatesOfParticles[i] = [x, y];
      }

      for(i = 0; i < coordinatesOfParticles.length - 1; i++) {
          for(j = i + 1; j < coordinatesOfParticles.length; j++) {
              if(math.distance(coordinatesOfParticles[i], coordinatesOfParticles[j]) < 190) {
                  ctx.beginPath();
                  ctx.lineWidth = getLineWidth(190, 90, math.distance(coordinatesOfParticles[i], coordinatesOfParticles[j]));
                  ctx.moveTo(coordinatesOfParticles[i][0], coordinatesOfParticles[i][1]);
                  ctx.lineTo(coordinatesOfParticles[j][0], coordinatesOfParticles[j][1]);
                  ctx.stroke();
              }
          }
      }
  }

  setInterval(draw, 1000/60);
}

【讨论】:

  • 很高兴您找到了解决方案。对于这类事情,我认为模拟物理总是给人一种自然的感觉。你可以使用任何物理引擎来完成它,或者编写你自己的小片段来获取粒子的当前速度和质量,并为其添加一个力来改变它的方向。每 n 秒随机改变该力。
  • @JonasGrumann 谢谢,有趣的想法,我会尝试这样做,它可能会比这更好,但我希望它保持在右侧(或任何一侧),所以它只是一个简单的设计元素,不会占用太多性能并变得滞后。另外,如果我将它模拟为具有质量和重力的东西,动画最终不会停止吗?我在编写这样的东西方面没有经验,我只是看到了那个动画,并把它作为对自己的挑战来创造类似的东西。
  • 我不认为只要你继续加力它就会停止。你可以有一个简单的公式来向屏幕的某个点或边缘添加一个力。它离目标点越远,它向它施加的力就越大。我不认为它会变得滞后,因为物理学主要是简单的计算,例如平方根、乘法等,所以对于浏览器来说真的很容易
  • 例如,看看这个演示的运行速度(并且它开启了碰撞):brm.io/matter-js/demo/#avalanche
猜你喜欢
  • 2015-07-06
  • 2017-03-02
  • 2021-12-25
  • 2022-01-06
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2016-09-08
  • 2016-03-15
相关资源
最近更新 更多