骑自行车的星空动画

时间:2017-04-02 06:42:16

标签: javascript animation canvas

我用javascript制作了这个星域动画。我不确定让它从另一侧循环相同动画的最佳方法。我喜欢让星星从画布的一边滚动到另一边。



var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
stars = [];
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, 500, 500);

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

function getSpeed(depth) {
  switch (depth / 2) {
    case 0:
      return 6;
    case 1:
      return 5;
    case 2:
      return 4;
    case 3:
      return 3;
    case 4:
      return 2;
    case 5:
      return 1;
  }
}
var i;
for (i = 0; i < 2000; i++) {
  var star = {
    x: 0,
    y: 0,
    z: 0,
    v: 0
  };
  star.x = getRandomInt(0, 500);
  star.y = getRandomInt(0, 500);
  star.z = getRandomInt(0, 5) * 2;
  star.v = getSpeed(star.z);
  stars.push(star);
}

function animation() {
  //clears background
  ctx.fillStyle = "#000000";
  ctx.fillRect(0, 0, 500, 500);

  // populates space with stars
  for (i = 0; i < 2000; i++) {
    ctx.fillStyle = "rgb(" + (256 / stars[i].z) + "," + (256 / stars[i].z) + "," + (256 / stars[i].z) + ")";
    ctx.fillRect(stars[i].x, stars[i].y, 2, 2);
    stars[i].x += stars[i].v;
  }

  setTimeout(animation, 33);
}
animation();
&#13;
<canvas id="myCanvas"></canvas>
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:2)

只要在x值低于零时重置x值。

if (star.x < 0) star.x = canvasWidth;

我做了一些其他的改动,比较。

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

function StarField(ctx, numStars, width, height) {
  var stars = new Array(numStars).fill(null).map(getStar);
  
  function getStar() {
    var z = getRandomInt(0, 5),
      c = (256 / z).toString(16);
    return {
      x: getRandomInt(0, width),
      y: getRandomInt(0, height),
      z: z * 2,
      v: 6 - z,
      c: "#" + c + c + c
    };
  }
  
  this.animate = function () {
    var i, s;

    ctx.fillStyle = "#000000";
    ctx.fillRect(0, 0, width, height);

    for (i = 0; i < numStars; i++) {
      s = stars[i];
      ctx.fillStyle = s.c;
      ctx.fillRect(s.x, s.y, 2, 2);
      s.x -= s.v;
      if (s.x < 0) s.x = width;
    }
    setTimeout(this.animate.bind(this), 32);
  };
}

var canvas = document.getElementById("myCanvas");
var s = new StarField(canvas.getContext("2d"), 2000, 500, 500);
s.animate();
<canvas id="myCanvas"></canvas>

答案 1 :(得分:1)

要反转

stars[i].x -= stars[i].v;

你可以永远循环,当i == 1999时,将v乘以-1并再次将i设为0

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
stars = [];
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, 500, 500);

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

function getSpeed(depth) {
  switch (depth / 2) {
    case 0:
      return 6;
    case 1:
      return 5;
    case 2:
      return 4;
    case 3:
      return 3;
    case 4:
      return 2;
    case 5:
      return 1;
  }
}
var i;
for (i = 0; i < 2000; i++) {
  var star = {
    x: 0,
    y: 0,
    z: 0,
    v: 0
  };
  star.x = getRandomInt(0, 500);
  star.y = getRandomInt(0, 500);
  star.z = getRandomInt(0, 5) * 2;
  star.v = getSpeed(star.z);
  stars.push(star);
}

function animation() {
  //clears background
  ctx.fillStyle = "#000000";
  ctx.fillRect(0, 0, 500, 500);

  // populates space with stars
  for (i = 0; i < 2000; i++) {
    ctx.fillStyle = "rgb(" + (256 / stars[i].z) + "," + (256 / stars[i].z) + "," + (256 / stars[i].z) + ")";
    ctx.fillRect(stars[i].x, stars[i].y, 2, 2);
    stars[i].x -= stars[i].v;
  }

  setTimeout(animation, 33);
}
animation();
<canvas id="myCanvas"></canvas>

答案 2 :(得分:1)

你可以通过添加新属性d(方向)看到星星双向移动,当星星到达屏幕末尾时方向会发生变化......

<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas"></canvas>
<script>

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
stars = [];
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, 500, 500);

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

function getSpeed( depth)
{
     switch(depth/2)
     {
       case 0:
         return 6;
       case 1:
         return 5;
       case 2:
         return 4;
       case 3:
         return 3;
       case 4:
         return 2;
       case 5:
         return 1;
     }
}
var i;
for (i = 0; i < 2000; i++) {
  var star= { x: 0, y: 0, z: 0, v: 0 };
  star.x = getRandomInt(0, 500);
  star.y = getRandomInt(0, 500);
  star.z = getRandomInt(0, 5) * 2;
  star.v = getSpeed(star.z);
  star.d = 1;
  stars.push(star);
}

function animation () {
  //clears background
  ctx.fillStyle = "#000000";
  ctx.fillRect(0, 0, 500, 500);

  // populates space with stars
  for (i = 0; i < 2000; i++) {
  ctx.fillStyle = "rgb(" + (256 / stars[i].z) + "," + (256 / stars[i].z) + "," + (256 / stars[i].z) + ")";
  ctx.fillRect(stars[i].x, stars[i].y, 2, 2);
  if(stars[i].x>=500)stars[i].d=-1;
  if(stars[i].x<=0)stars[i].d=1;
  stars[i].x += stars[i].v * stars[i].d;	
 }

   setTimeout(animation, 33);
}
animation ();

</script>
</body>
</html>

答案 3 :(得分:1)

移动并重复使用余数运算符%。因为它返回负值,所以你必须弄得一点点,以确保数字总是正数。此外,您还希望确保星星在​​完全偏离一侧时仅移动到画布的另一侧,因此模数值必须包含星号500+2

因此star pos x

x %= 502;  // get remainder could be negative
x += 502;  // ensure it is positive
x %= 502;  // do modulo again

我是如何在你的例子中做到的

// set up
var w = canvas.width;
var h = canvas.height;
const starCount = 2000;
const starSize = 2;
const widthModulo = w + starSize;
const heightModulo = h + starSize;

   // in iteration

    x = ((star.x % widthModulo) + widthModulo) % widthModulo - starSize / 2;
    y = ((star.y % heightModulo) + heightModulo) % heightModulo - starSize / 2;
    // draw the star
    ctx.fillRect(x, y, starSize, starSize);

我已经更改了您的代码,让星星向多个方向展示,以显示此方法的效果。还添加了一些其他更改。主要是使用requestAnimationFrame来调用动画函数。

&#13;
&#13;
var ctx = canvas.getContext("2d");
const stars = [];
var dir = Math.PI;
var w = canvas.width;
var h = canvas.height;
const starCount = 2000;
const starSize = 2;
const widthModulo = w + starSize;
const heightModulo = h + starSize;

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

var i;
for (i = 0; i < starCount; i++) {

  // following 4 randoms give a semi bell curve to the random value
  // this is to make more star at lower z values
  var z = (Math.random() + Math.random() +Math.random() +Math.random());
  z = Math.abs(z-2) * 8;
  var col = Math.floor(16 * z);
  stars.push({
    x: getRandomInt(0, w),
    y: getRandomInt(0, h),
    v: z / 6,
    col : "rgb("+col+","+col+","+col+")",
  });
}
stars.sort((a,b)=>a.v - b.v);  // sort from back to front

function animation (timer) {
  var star, dx, dy, x, y, i;

  // set the direction to make stars move in long circles
  dir = (Math.sin(timer / 13289) + 1) * Math.PI ; 

  //clears background
  ctx.fillStyle = "#000000";
  ctx.fillRect(0, 0, w, h);

  // get direction vector
  dx = Math.cos(dir);
  dy = Math.sin(dir);
  for (i = 0; i < starCount; i += 1) {
    star = stars[i];
    ctx.fillStyle = star.col;

    // move the star
    star.x += star.v * dx;
    star.y += star.v * dy;

    // make sure that stars are rendered on the current viewport
    x = ((star.x % widthModulo) + widthModulo) % widthModulo - starSize / 2;
    y = ((star.y % heightModulo) + heightModulo) % heightModulo - starSize / 2;
    // draw the star
    ctx.fillRect(x, y, starSize, starSize);
  }

  requestAnimationFrame(animation);
}
requestAnimationFrame(animation);
&#13;
<canvas id=canvas width = 500 height = 500></canvas>
&#13;
&#13;
&#13;