just out of fun I made that little toy top (gyroscope?), using Javascript and Canvas. Unfortunately there's an ugly Moiré effect on it (see screenshot below). http://jsfiddle.net/8bac4s9v/1/
function draw() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.imageSmoothingEnabled = false;
var colors = [
['blue', 'yellow'],
['white', 'pink'],
['green', 'red'],
['white', 'black'],
['green', 'blue'],
['red', 'green', 'blue']
];
for (var i = 0; i < 12; i++) {
for (var cIdx = 0, p = 0; p < 120; p += 20, cIdx++) {
var cols = colors[cIdx];
for (var r = p; r < p + 20; r++) {
ctx.beginPath();
ctx.arc(125, 125, r, (i - 1) * Math.PI / 6.0, i * Math.PI / 6.0);
ctx.strokeStyle = cols[i % cols.length];
ctx.stroke();
}
}
}
}
I guess, that moiré effect comes from anti-aliasing. So I thought, I could get rid of
that Moiré effect when I switch off anti-aliasing with ctx.imageSmoothingEnabled = false
.
But no, nothing changes.
Any ideas?
Thanks, Bernhard
This is how it looks:
The effect you're seeing basically is aliasing, so if anything, you would want to enable anti-aliasing. However, the imageSmoothingEnabled property is only used for pattern fills or drawImage, so it doesn't have any effect here.
For your example, instead of drawing 1px-wide concentric circles that change colors for every 20px increase in radius, I would recommend that you instead just draw 20px-wide concentric circles. That will solve the aliasing effect, and it also gets rid of one of your inner loops, so it should be a bit more efficient. Here's an updated fiddle - besides removing the loop, I also adjusted the boundary conditions on the loops as well:
http://jsfiddle.net/foskc95k/2/
ctx.lineWidth = 21;
for (var i = 0; i < 12; i++) {
for (var cIdx = 0, r = 10; r <= 110; r += 20, cIdx++) {
var cols = colors[cIdx];
ctx.beginPath();
ctx.arc(125, 125, r, (i - 1) * Math.PI / 6.0, i * Math.PI / 6.0);
ctx.strokeStyle = cols[i % cols.length];
ctx.stroke();
}
}
Note also that I'm actually using a lineWidth of 21px instead of 20px because it seems to leave a 1px wide gap otherwise (I'm not sure why).
You can increase the lineWidth of the context, eg ctx.lineWidth=2, that will solve the Moiré effect.
...
var ctx = c.getContext("2d");
ctx.imageSmoothingEnabled = false;
ctx.lineWidth=2;
...
http://jsfiddle.net/p4obo996/
But I think your gyroscope implementation is not very good. You should find a solutions that uses ctx.fillStyle and ctx.fill() instead of ctx.strokeStyle to set the color.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With