Цвета, которые меняются с течением времени на холсте (js) / Проблемы с setInterval - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь сделать анимацию на холсте, где есть только сплошной прямоугольник, который смещается с белого на красный, с зеленого на синий, а затем снова на белый. Я думаю, что цвета работают нормально, но это происходит слишком быстро, чтобы что-то увидеть, поэтому я искал вариант ожидания или задержки и наткнулся на метод setInterval. Я старался изо всех сил, чтобы все заработало, но безуспешно

Вот несколько чистый код, который я сделал.

HTML:

<!DOCTYPE html>
<html>
<head>
      <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <style type="text/css">
      canvas { border: 3px solid black; }
  </style>
</head>
<body>
  <div>
    <button onclick="draw()">Start the gradient</button><br><br>
    <canvas id="can" width="200" heigth="200"></canvas>
  </div>
</body>
</html>

Javascript:

function draw() {
  var can = document.getElementById('can');
  if (can.getContext) {
    var ctx = can.getContext('2d');
    var r = 0;
    var g = 0;
    var b = 0;
    var i;
    for(i=0;i<255;i++){
          ctx.fillStyle = 'rgb('+r+', '+g+', '+b+')';
          ctx.fillRect(0, 0, 200, 200);
          r = r + 1;
    }
    for(i=0;i<255;i++){
          ctx.fillStyle = 'rgb('+r+', '+g+', '+b+')';
          ctx.fillRect(0, 0, 200, 200);
          r = r - 1;
          g = g + 1;
    }
    for(i=0;i<255;i++){
          ctx.fillStyle = 'rgb('+r+', '+g+', '+b+')';
          ctx.fillRect(0, 0, 200, 200);
          g = g - 1;
          b = b + 1;
    }
    for(i=0;i<255;i++){
          ctx.fillStyle = 'rgb('+r+', '+g+', '+b+')';
          ctx.fillRect(0, 0, 200, 200);
          r = r + 1;
          g = g + 1;
    }
  }
//'can' is the canvas//
//Red->Green->Blue//
}

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

То, с чем вы имеете дело, - это основы работы анимации.

Чтобы анимация работала, вам нужно, как неупорядоченный список,

  • сцена , с некоторыми элементами, которые зритель должен иметь возможность идентифицировать какперсонажи, или, в вашем случае, сплошной цвет.
  • средство визуализации , которое хорошо отразит вашу сцену в некоторой графической форме.Это может быть рисунок рукой на углу ноутбука в случае низкорамной флип-книги или функция рисования в случае компьютерной графики.
  • движок , что-то такое, чтообновит положение наших движущихся элементов в сцене и представит следующую визуализированную графику, отмеченную галочкой через определенный промежуток времени.Проведите пальцем по флипбуку, некоторые методы, основанные на времени, в компьютерной графике.setInterval - это один из таких методов, но лучше начать прямо с правильного инструмента, поэтому позвольте мне представить вам requestAnimationFrame , который является лучшим способом задействовать графическую анимацию в браузере.В основном, это запланирует функцию обратного вызова до следующего обновления экрана, позволяя всегда синхронизировать анимацию с наилучшей экономией энергии.

Итак, давайте создадим ее;)

Элементами нашей сцены в вашем случае могут быть только три компонента сплошного цвета, который мы будем анимировать:

const color = [255, 255, 255]; // [red, green, blue]

Средство визуализации возьмет его анимацию.Поскольку в вашей настройке есть несколько ключевых кадров , необходимо вычислить между кадрами.Здесь я просто покажу базовый движок приращения кадров, но было бы лучше использовать основанный на времени, но я подумал, что сейчас это может быть слишком много ...

Так что мы будем держать переменную позицииздесь, после вызова currentFrame, чтобы мы могли знать, где мы находимся в анимации, от какого ключевого кадра к какому другому мы идем, и вычислить правильные значения для нашего промежуточного кадра.На каждой итерации (каждом кадре) мы будем увеличивать эту переменную до тех пор, пока не достигнем общего количества кадров, из которых будет создана наша анимация.На этом этапе мы сможем запустить его снова, используя оператор по модулю %.

const color = [255, 255, 255]; // [red, green, blue]
const keyFrames = [
  [255, 255, 255], // white
  [255, 0, 0], // to red
  [0, 255, 0], // to green
  [0, 0, 255] // to blue
];
const duration = 5; // in seconds
const totalFrames = 60 * duration; // 60 FPS
let currentFrame = 0;

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

function update() {
  // update currentFrame, relative to the whole animation duration
  currentFrame = (currentFrame + 1) % totalFrames;
  // make it relative to our key-frames
  const keyFrameIndex = currentFrame / (totalFrames / keyFrames.length);
  // Now we know our previous and next key-frames
  const prev = keyFrames[Math.floor(keyFrameIndex) % keyFrames.length];
  const next = keyFrames[Math.ceil(keyFrameIndex) % keyFrames.length];
  // We need to get the in-between ratio (that's the decimal of our floating index)
  const inBetweenRatio = keyFrameIndex - Math.floor(keyFrameIndex);
  //now we can update our color
  calculateInBetween(color, prev, next, inBetweenRatio);
}

function calculateInBetween(color, prev, next, ratio) {
  // simply update each channel of our current color
  color[0] = Math.floor((next[0] - prev[0]) * ratio) + prev[0];
  color[1] = Math.floor((next[1] - prev[1]) * ratio) + prev[1];
  color[2] = Math.floor((next[2] - prev[2]) * ratio) + prev[2];
}

function draw() {
  // clear all
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // render
  ctx.fillStyle = "rgb(" + color + ")";
  ctx.fillRect(0, 0, 200, 200);
}

// our animation loop
function anim() {
  // update the scene
  update();
  // then render it
  draw();
  // start again at next screen refresh
  requestAnimationFrame(anim);
}


// let's begin
anim();
<canvas id="canvas" width="200" height="200"></canvas>
0 голосов
/ 19 ноября 2018

Вот быстрый и грязный способ. Вы установили кучу тайм-аутов в начале:

function draw() {
    var can = document.getElementById('can');
    if (can.getContext) {
        var ctx = can.getContext('2d');
        var r = 0;
        var g = 0;
        var b = 0;
        var i;
        var numColors = 255;
        var delay = 0; // ms
        var delta = 5; // ms

        for (i = 0; i < numColors; i++) {
            delay += delta;
            setTimeout(function () {
                ctx.fillStyle = 'rgb(' + r + ', ' + g + ', ' + b + ')';
                ctx.fillRect(0, 0, 200, 200);
                r = r + 1;
            }, delay);
        }

        for (i = 0; i < numColors; i++) {
            delay += delta;
            setTimeout(function () {
                ctx.fillStyle = 'rgb(' + r + ', ' + g + ', ' + b + ')';
                ctx.fillRect(0, 0, 200, 200);
                r = r - 1;
                g = g + 1;
            }, delay);
        }

        for (i = 0; i < numColors; i++) {
            delay += delta;
            setTimeout(function () {
                ctx.fillStyle = 'rgb(' + r + ', ' + g + ', ' + b + ')';
                ctx.fillRect(0, 0, 200, 200);
                g = g - 1;
                b = b + 1;
            }, delay);
        }

        for (i = 0; i < numColors; i++) {
            delay += delta;
            setTimeout(function () {
                ctx.fillStyle = 'rgb(' + r + ', ' + g + ', ' + b + ')';
                ctx.fillRect(0, 0, 200, 200);
                r = r + 1;
                g = g + 1;
            }, delay);
        }
    }
}
...