Reputation: 121
I am experimenting with drawing using javascript and the canvas element..my goal now is to draw a circle and gradually increase the opacity; I have this code:
http://codepen.io/anon/pen/zrVvOQ
Which seems to work, but the circle has rough edges; I found I need to clear the canvas each time the frame is redrawn, but the attempts I have made have not quite worked...any suggestions on how to?
window.onload = function draw(){
var frame1 = document.getElementById('frame1');
if (frame1.getContext){
var ctx = frame1.getContext('2d');
var centerX = frame1.width / 2;
var centerY = frame1.height / 2;
var radius = 50;
var alpha = 1.0;
/*call function over and over */
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
var rendergreen = function()
{
var opacityValue = 0;
opacityValue += 0.03;
ctx.fillStyle = 'rgba(68,107,62, ' + opacityValue + ')';
animate();
ctx.arc(50, centerY, radius, 0, 2 * Math.PI, false);
ctx.clip();
ctx.fill();
ctx.closePath;
function animate() {
if (opacityValue < 1) {
opacityValue += 0.3;
} else {
opacityValue = 1;
}
}
requestAnimationFrame(rendergreen);
}
rendergreen();
}
}
Upvotes: 0
Views: 775
Reputation: 12458
You say the circle has "rough edges". That's pixellation and is inherent in using canvas
to draw, which is a bit-mapped style of graphics. That means that you essentially can't get higher resolution than a single pixel. Contrast that with svg
which is vector-based. An svg
image can be magnified a thousand times and still have a smooth edge. I've shown an svg circle next to the canvas circle so that you can see the difference. It becomes much more apparent if you zoom in with your browser. There are pro's and con's to using canvas vs svg, too much to go into here, but it's worth looking into if you're really concerned.
In terms of changing the opacity of the circle, you've got several problems with your approach. With the way you've written it, you're actually not changing the opacity. Instead, you're drawing the same very transparent circle many times over top of each other so that by the end it looks opaque, giving the impression that you are gradually increasing the transparency of a single circle. Notice that you're setting your opacity to zero in each drawing iteration, then incrementing it to 0.05 (note that there are differences in the code in your question versus in the codepen that you linked to...I'm referring to the codepen version), then drawing it (so it will always be drawn at opacity 0.05), then further changing the value of the variable opacityValue
which is never used in the drawing. The example below shows a relatively simple example of what I think you were trying to achieve. Note that I've deliberately made the 'clearRect' too small so that you can see how not clearing the canvas each time allows semi-transparent drawings to "pile up". This also allows you to see that the blockiness gets worse if you overlay many semi-transparent images. e.g. Compare the left and right sides of the canvas circle. The part of the circle that is cleared every time ends up looking smoother because of anti-aliasing, but the overlaid images have the smoothing effects of anti-aliasing effectively destroyed.
window.onload = function draw() {
var frame1 = document.getElementById('frame1');
if (frame1.getContext) {
var ctx = frame1.getContext('2d');
var opacityValue = 0;
var render = function() {
ctx.clearRect(0, 0, 80, 80); // deliberately set too small
ctx.beginPath();
opacityValue += 0.01;
ctx.fillStyle = 'rgba(68,107,62, ' + opacityValue + ')';
ctx.arc(60, 60, 50, 0, 2 * Math.PI, false);
ctx.fill();
ctx.closePath;
requestAnimationFrame(render);
}
render();
}
}
<canvas id="frame1" width="120" height="120"></canvas>
<svg width="120" height="120">
<circle cx="60" cy="60" r="50" fill="#446B3E"></circle>
</svg>
Upvotes: 1