Reputation: 1739
I need to animate a circle moving in a html canvas. For this purpose, I decided to use a typical sprite animation technique which consist in the following general steps:
My problem is that the result looks like all the old circles seem to be redrawn each time I call ctx.fill()
despite I am reseting the canvas.
What am I doing wrong? Any suggestion?
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>
Upvotes: 2
Views: 554
Reputation: 17594
I see you already figured out to use the beginPath
but I will disagree with the location I will put that at the very beginning of the function animate, take a look at the code below, I refactored your code, got rid of some unused variables, and made the slider an object just like you have for the knob
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>
Upvotes: 1
Reputation: 1739
Ok, I found the cause: the arc()
method stacks the circle as part of the path, so, for it to work, we need to reset the path like this:
draw() {
ctx.fillStyle = rgbToHex(0, 2*y, 107);
ctx.beginPath();
ctx.arc(8, this.position.y, 7, 0, 2 * Math.PI);
ctx.fill();
}
Upvotes: 1