Анимационный круг в HTML-холсте с использованием JavaScript - PullRequest
2 голосов
/ 19 мая 2019

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

  1. Инициализация фона (в данном случае просто серый прямоугольник)
  2. Рассчитать координаты нового спрайта
  3. Нарисуй спрайт (круг)
  4. Сбросить фон
  5. Перейти к 2

Моя проблема в том, что результат выглядит так, как будто все старые круги кажутся перерисованными каждый раз, когда я звоню ctx.fill(), несмотря на то, что я сбрасываю холст.

Что я делаю не так? Любое предложение?

        var canvas;
        var ctx;
        var canvasPos;

        function rgbToHex(r, g, b) {
            return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
        }

        function init() {
            canvas = document.getElementById("target_temp");
            ctx = canvas.getContext("2d");
            canvasPos = { x: canvas.offsetLeft, y: canvas.offsetTop };
            drawSlider();
        }

        var y = 7;

        function animate() {
            y = y + 1;

            knob.setPosition(8, y);
            knob.clear();
            knob.draw();

            if (y < 93) {
                setTimeout(animate, 10);
            }
        }

        function drawSlider() {
            ctx = canvas.getContext("2d");
            ctx.fillStyle = "#d3d3d3";
            ctx.fillRect(0, 0, 16, 100);
        }

        var knob = {
            position: { x: 8, y: 7 },
            oldPosition: { x: 8, y: 7 },
            setPosition(_x, _y) {
                this.oldPosition = this.position;
                this.position.x = _x;
                this.position.y = _y
            },
            clear() {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                drawSlider();
            },
            draw() {
                ctx.fillStyle = rgbToHex(0, 0, 112);              
                ctx.arc(8, this.position.y, 7, 0, 2 * Math.PI);
                ctx.fill();
            }
        }

        window.onload = function () { init(); animate(); };
<!DOCTYPE html>
<html>
<boyd>
    <canvas id="target_temp" width="16px" height="100px"></canvas>
</boyd>
</html>

Ответы [ 2 ]

1 голос
/ 19 мая 2019

Я вижу, вы уже разобрались в использовании beginPath, но я не согласен с местоположением. Я добавлю, что в самом начале функции animate, посмотрите на код ниже, я реорганизовал ваш код, избавился некоторых неиспользуемых переменных, и сделал ползунок объектом, как у вас для ручки

var canvas = document.getElementById("target_temp");
var ctx = canvas.getContext("2d");

var slider = {
  width: 16, 
  height: 100,
  draw() {
    ctx.fillStyle = "#d3d3d3";
    ctx.fillRect(0, 0, this.width, this.height);
  }
}

var knob = {
  position: {x: 8, y: 7},
  radius: 8,
  draw() {    
    ctx.fillStyle = "#00D";    
    ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI);
    ctx.fill();
  }
}

function animate() {
  ctx.beginPath()
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  slider.draw();
  if (knob.position.y + knob.radius < slider.height) 
    knob.position.y++;  
  knob.draw();
  setTimeout(animate, 10);
}

window.onload = function() {
  animate()
};
<canvas id="target_temp"></canvas>
1 голос
/ 19 мая 2019

Хорошо, я нашел причину: метод arc() складывает круг как часть пути, поэтому, чтобы он работал, нам нужно сбросить путь следующим образом:

draw() {
  ctx.fillStyle = rgbToHex(0, 2*y, 107);      
  ctx.beginPath();          
  ctx.arc(8, this.position.y, 7, 0, 2 * Math.PI);
  ctx.fill();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...