【问题标题】:Canvas animation with JavaScript. Random coordinates and speed at every initiation使用 JavaScript 的画布动画。每次启动时的随机坐标和速度
【发布时间】:2018-01-05 22:04:53
【问题描述】:

已编辑:感谢大家宝贵的时间和精力。最后我做了这个))JSfiddle

我只是在玩画布并制作了这个。小提琴链接here.

... some code here ...

var cords = [];

for(var i = 50; i <= width; i += 100) {
  for(var j = 50; j <= height; j += 100) {
    cords.push({ cor: i+','+j});
  }
}

console.log(cords);

var offset = 15,
    speed = 0.01,
    angle = 0.01;

cords.forEach(function(e1) {
  e1.base = parseInt(Math.random()*25);
  e1.rgb = 'rgb('+parseInt(Math.random()*255)+','+parseInt(Math.random()*255)+','+parseInt(Math.random()*255)+')';
});

setInterval(function() {
  cords.forEach(function(e1) {
    e1.base = parseInt(Math.random()*25);
    e1.rgb = 'rgb('+parseInt(Math.random()*255)+','+parseInt(Math.random()*255)+','+parseInt(Math.random()*255)+')';
  });
},5000);

function render() {

  ctx.clearRect(0,0,width,height);

  cords.forEach(function(e1) {
    //console.log(e1);
    ctx.fillStyle = e1.rgb;
    ctx.beginPath();
    var r = e1.base + Math.abs(Math.sin(angle)) * offset;
    var v = e1.cor.split(',');
    ctx.arc(v[0],v[1],r,0,Math.PI * 2, false);
    ctx.fill();
  });
  angle += speed;
  requestAnimationFrame(render);
}

render();

想知道如果 -

  1. 坐标可以是随机的,现在它们是固定的,如您所见。 5000 百万之后,球会出现在各种随机的绳索中,但即使在最大的时候,它们也不会相互接触。
  2. 每个球都有相同的速度来改变大小,我也希望那是不同的。这意味着,在 50 亿之后,它们也会以不同的动画速度出现。

也非常感谢任何有关改进代码并使其更好/更快/更轻的建议。谢谢!

【问题讨论】:

  • 在圆圈对象中定义速度和角度jsfiddle.net/v9x1gpLq/5
  • @Kaiido 谢谢,但我希望绳索在每次初始化时都是随机的。见this
  • 好吧,添加它。这只是一个评论,让您了解如何处理一般问题的基础知识。现在您知道了,您可以为您的对象添加任何单一属性。

标签: javascript html animation canvas


【解决方案1】:

TL;DR - 看到它正在运行here

使坐标随机化:

这需要您在 x 和 y 坐标上添加一些随机位移。所以我在坐标中添加了一个随机值。但是小于 1 的位移并不明显。因此,您需要将该随机数放大一个乘数。这就是randomizationFactor 出现的地方。我已将其设置为100,因为这是您在每次迭代中移动坐标的值。这样一来,动画就呈现出真正随机的外观。

使速度随机:

我花了一段时间才弄清楚,但理想的方法是将速度值推入坐标数组。这让您可以确保在动画的持续时间内,速度将保持恒定,从而为您带来更流畅的感觉。但是再次将半径 r 乘以 0 到 1 之间的值会显着降低某些圆的速度。所以我在 3 上加了一个乘数来稍微补偿一下。

理想情况下,我会设置 2,因为 Math.random() 的平均值是 0.5,所以乘以 2 就足以弥补这一点。但是一点实验表明,乘数 3 要好得多。您可以根据自己的喜好选择值。

您生成坐标的逻辑如下:

for(var i = 50; i <= width;i += 100)  {
  for(var j = 51; j <= height;j += 100) {
    var x = i + (Math.random() - 0.5)*randomizationFactor;
    var y = j + (Math.random() - 0.5)*randomizationFactor;
    cords.push({ cor: x+','+y, speed: Math.random()});
  }
}

你放大圆圈的逻辑变化如下:

function render() {

  ctx.clearRect(0,0,width,height);

  cords.forEach(function(e1) {
    //console.log(e1);
    ctx.fillStyle = e1.rgb;
    ctx.beginPath();
    var r = e1.base + Math.abs(Math.sin(angle)) * offset * e1.speed * 3;
    var v = e1.cor.split(',');
    ctx.arc(v[0],v[1],r,0,Math.PI * 2, false);
    ctx.fill();
  });
  angle += speed ;
  requestAnimationFrame(render);
}

建议:用颜色更新坐标

我可能还会每 5 秒更新一次圆圈的位置以及颜色。做起来也很简单。 Here 我刚刚创建了一个函数 resetCoordinates,它与 setBaseRgb 函数一起每 5 秒运行一次。

var cords = [];
function resetCoordinates() {
  cords = [];

  for(var i = 50; i <= width;i += 100)  {
    for(var j = 51; j <= height;j += 100) {
      var x = i + (Math.random() - 0.5)*randomizationFactor;
      var y = j + (Math.random() - 0.5)*randomizationFactor;
      cords.push({ cor: x+','+y, speed: Math.random()});
    }
  }
}

【讨论】:

  • 非常感谢。一件事,球彼此重叠。我们怎样才能防止这种情况发生。其他一切都很酷!
  • 其中一种方法是保持 randomizationFactor 略小,速度乘数更小(正如我所提到的)。 Here我分别保持了50和1.5,球很少相互接触。实现相同效果的另一种方法是计算球是否会相互接触,然后修改它们的坐标以避免这种情况。但这对我来说似乎太乏味了。
  • 非常正确。看着它,如果一个球变得很大,很有可能重叠。
【解决方案2】:

更新我在您的代码中做了一些修复,可以使您的动画更加动态。完全重写的样本。 (抱歉更改了变量名,imo 现在更好了)

内置Math.random 并不是真正随机的,当你遇到动画时会变得很明显。尝试使用这个random-js lib。

var randEngine = Random.engines.mt19937().autoSeed();
var rand = function(from, to){
  return Random.integer(from, to)(randEngine)
}

每个圆圈的内部基础属性会更好(更动态)。

var circles = [];

// better to save coords as object neither as string
for(var i = 50; i <= width; i += 100)
  for(var j = 50; j <= height; j += 100)
   circles.push({ 
    coords: {x:i,y:j}
   });

我们可以使用新的弹跳属性来调整动画。

var offset = 15,
    speed = 0.005,
    angle = 0.01,
    bouncing = 25;

这就是setBaseRgb 函数的样子

function setBaseRgb(el){
  el.base = rand(-bouncing, bouncing);
  el.speed = rand(5, 10) * speed;
  el.angle = 0;
  el.rgb = 'rgb('+rand(0, 255)+','+rand(0, 255)+','+rand(0, 255)+')';
}

您的所有动画都已修复 setInterval 超时。随机超时更好。

cords.forEach(function(el){
  // random timeout for each circle
  setInterval(setBaseRgb.bind(null,el), rand(3000, 5000));
})

你忘记将你的基地添加到你的圈子位置

function render() {    

  ctx.clearRect(0,0,width,height);

  circles.forEach(function(el) {
    ctx.fillStyle = el.rgb;
    ctx.beginPath();
    var r = bouncing + el.base + Math.abs(Math.sin(el.angle)) * offset;
    var coords = el.coords;
    ctx.arc(
       coords.x + el.base,
       coords.y + el.base,
       r, 0, Math.PI * 2, false
    );
    ctx.fill();
    el.angle += el.speed;
  });
  requestAnimationFrame(render);
}

render();

效果1 JSFiddle

添加这个

if(el.angle > 1)
  el.angle=0;

结果冒泡效果

效果2 JSFiddle

玩公式会导致这个

效果3 JSFiddle

【讨论】:

  • 我喜欢打破一次更新所有球的过程的想法!看起来很有趣。
  • 是的,这很有趣!完全不同的看法。谢谢!但是绳子是一样的。我喜欢他们改变了。不一样的行和列一次又一次。 ;)
  • 谢谢你们。我现在会尝试修复它。
  • 太酷了。我们如何更改尺寸因子以停止重叠。喜欢jsfiddle.net/v9x1gpLq/11
  • 哈哈 .. 问题:windows 是否提供任何方式来使用这样的东西,活的东西,作为桌面壁纸或背景哈哈
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
  • 1970-01-01
相关资源
最近更新 更多