requestAnimationFrame, не получается зациклить

193
15 июля 2018, 15:10

Модернизирую найденный код. В оригинале клочья тумана проходят снизу вверх по canvas, и исчезают. Я пытаюсь добиться, чтобы ставшая max высота установилась в 0 (точнее наоборот, идем снизу вверх), и анимация зациклилась. Я пока не до конца поняла природу переменной var td = new Date().getTime() - p.start; Математически это вообще (-delay), но переменная постоянно растет (повязанна на реальном времени?)

if (p.newTop < 0)
    {   
        newTop = 100;
    }

Переместить в координату 100 (100 чисто для наглядности) получилось. А вот "обнулить" td, чтобы присвоить ее newTop для нового витка, не получается.

const TIMEOUT = 40; 
var stTime = 0; 
canvasWidth = 1600; 
canvasHeight = 200; 
pCount = 0; 
pCollection = new Array(); 
var puffs = 1; 
var particlesPerPuff = 50; //2000 
var img = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/85280/smoke2.png'; 
var smokeImage = new Image(); 
smokeImage.src = img; 
 
for (var i1 = 0; i1 < puffs; i1++) { 
  var puffDelay = i1 * 1500; 
  for (var i2 = 0; i2 < particlesPerPuff; i2++) { 
    addNewParticle((i2 * 50) + puffDelay); 
  } 
} 
 
draw(new Date().getTime(), 3000); 
 
function addNewParticle(delay) { 
  var p = {}; 
  p.top = canvasHeight; 
  p.left = randBetween(-200, 800); 
  p.start = new Date().getTime() + delay; 
  p.life = 8000; 
  p.speedUp = 30; 
  p.speedRight = randBetween(0, 20); 
  p.startOpacity = .3 
  p.newTop = p.top; 
  p.newLeft = p.left; 
  p.size = 200; 
  p.growth = 10; 
 
  pCollection[pCount] = p; 
  pCount++; 
} 
 
function draw(time) { 
  var c = document.getElementById("myCanvas"); 
  var ctx = c.getContext("2d"); 
  ctx.clearRect(0, 0, c.width, c.height); 
 
  for (let i = 0; i < pCount; i++) { 
    var p = pCollection[i]; 
    var td = new Date().getTime() - p.start; 
    console.log(td); 
    var frac = td / p.life 
    var newTop = p.top - (p.speedUp * (td / 1000)); 
    var newLeft = p.left + (p.speedRight * (td / 1000)); 
    var newOpacity = Math.max(p.startOpacity * (1), 0); 
    //var newOpacity = Math.max(p.startOpacity * (1-frac),0); 
    var newSize = p.size + (p.growth * (td / 1000)); 
    p.newTop = newTop; 
    p.newLeft = newLeft; 
 
 
    if (p.newTop < 0) { 
      //td = new Date().getTime() - p.start; 
      newTop = 100; 
    } 
 
 
    ctx.fillStyle = 'rgba(150,150,150,' + newOpacity + ')'; 
    ctx.globalAlpha = newOpacity; 
    ctx.drawImage(smokeImage, newLeft, newTop, newSize, newSize); 
  } 
 
  requestAnimationFrame(draw); 
} 
 
function randBetween(n1, n2) { 
  var r = (Math.random() * (n2 - n1)) + n1; 
  return r; 
}
body { 
  background: black url(https://s.cdpn.io/16327/texture_bg.jpg) no-repeat 50% 0px; 
} 
 
#myCanvas { 
  height: 300px; 
  width: 2400px; 
  max-width: 99%; 
  min-width: 800px; 
  position: absolute; 
  bottom: 0; 
  z-index: 2; 
} 
 
#house { 
  position: absolute; 
  top: 20%; 
  left: 40%; 
}
<canvas id="myCanvas" height="200" width="800"></canvas>

https://jsfiddle.net/Nata_Hamster/ut42nb5e/2/
Answer 1

Логика работы анимации в вашем примере такая:

  1. Создается элемент Particle. Ему, помимо прочих свойств, устанавливается время создания p.start = new Date().getTime() + delay,

    • new Date().getTime() - текущее время в миллисекундах

    • delay - задержка появления

  2. Затем, во время отрисовки элемента высчитывается его положение var newTop = p.top - (p.speedUp * (td / 1000));

    • p.top - начальное положение
    • p.speedUp - скорость всплытия
    • td - разница во времени в миллисекундах между текущим временем и временем начала var td = new Date().getTime() - p.start.

В итоге мы видим, что положение элемента в формуле var newTop = p.top - (p.speedUp * (td / 1000)); зависит от начального положения(p.top), скорости(p.speedUp) и разницы времени(td). Переменные начального положения(p.top) и скорости(p.speedUp) не меняются - они константа для элемента.

Следовательно, положение элемента зависит от времени(td). Значит, вам надо поменять начальное значение времени, что бы задать положение элементу. Значит вам надо написать код p.start = new Date().getTime().

Пример внизу.

const TIMEOUT = 40; 
var stTime = 0; 
canvasWidth = 1600; 
canvasHeight = 200; 
pCount = 0; 
pCollection = new Array(); 
var puffs = 1; 
var particlesPerPuff = 50; //2000 
var img = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/85280/smoke2.png'; 
var smokeImage = new Image(); 
smokeImage.src = img; 
 
for (var i1 = 0; i1 < puffs; i1++) { 
  var puffDelay = i1 * 1500; 
  for (var i2 = 0; i2 < particlesPerPuff; i2++) { 
    addNewParticle((i2 * 50) + puffDelay); 
  } 
} 
 
draw(new Date().getTime(), 3000); 
 
function addNewParticle(delay) { 
  var p = {}; 
  p.top = canvasHeight; 
  p.left = randBetween(-200, 800); 
  p.start = new Date().getTime() + delay; 
  p.life = 8000; 
  p.speedUp = randBetween(10, 40); // делаем разную скорость, чтобы смотрелось красивее 
  p.speedRight = randBetween(0, 20); 
  p.startOpacity = .3 
  p.newTop = p.top; 
  p.newLeft = p.left; 
  p.size = 200; 
  p.growth = 10; 
 
  pCollection[pCount] = p; 
  pCount++; 
} 
 
function draw(time) { 
  var c = document.getElementById("myCanvas"); 
  var ctx = c.getContext("2d"); 
  ctx.clearRect(0, 0, c.width, c.height); 
 
  for (let i = 0; i < pCount; i++) { 
    var p = pCollection[i]; 
    var td = new Date().getTime() - p.start; 
    var frac = td / p.life 
    var newTop = p.top - (p.speedUp * (td / 1000)); 
    var newLeft = p.left + (p.speedRight * (td / 1000)); 
    var newOpacity = Math.max(p.startOpacity * (1), 0); 
    //var newOpacity = Math.max(p.startOpacity * (1-frac),0); 
    var newSize = p.size + (p.growth * (td / 1000)); 
 
    if (newTop <= 0) { 
      p.start = new Date().getTime(); // обнуляем начальное время анимации start 
    } 
 
 
    ctx.fillStyle = 'rgba(150,150,150,' + newOpacity + ')'; 
    ctx.globalAlpha = newOpacity; 
    ctx.drawImage(smokeImage, newLeft, newTop, newSize, newSize); 
  } 
 
  requestAnimationFrame(draw); 
} 
 
function randBetween(n1, n2) { 
  var r = (Math.random() * (n2 - n1)) + n1; 
  return r; 
}
body { 
  background: black url(https://s.cdpn.io/16327/texture_bg.jpg) no-repeat 50% 0px; 
} 
 
#myCanvas { 
  height: 300px; 
  width: 2400px; 
  max-width: 99%; 
  min-width: 800px; 
  position: absolute; 
  bottom: 0; 
  z-index: 2; 
} 
 
#house { 
  position: absolute; 
  top: 20%; 
  left: 40%; 
}
<canvas id="myCanvas" height="200" width="800"></canvas>

READ ALSO
Почему post становится get?

Почему post становится get?

Пишу отправку сообщений на Django сервере и столкнулся с такой проблемой: при нажатии на input типа submit в форме типа post происходит передача методом...

175
Как сделать сборку webpack для frontend?

Как сделать сборку webpack для frontend?

Разбираюсь с webpack, столкнулся с ошибкой

169