I am trying to draw a smooth oval using ctx.clip property in my canvas.I have done with drawing part i am facing problem with oval arc line clarity.Any one have any idea regarding this just let me know? Here is my code.
<canvas id="c" width="400" height="400"></canvas>
var canvas = new fabric.Canvas('c');
var ctx = canvas.getContext('2d');
var cx=180;
var cy=200;
var w=300;
var h=250;
// Quadratric curves example
ctx.beginPath();
var lx = cx - w/2,
rx = cx + w/2,
ty = cy - h/2,
by = cy + h/2;
var magic = 0.551784;
var xmagic = magic*w/2;
var ymagic = h*magic/2;
ctx.moveTo(cx,ty);
ctx.bezierCurveTo(cx+xmagic,ty,rx,cy-ymagic,rx,cy);
ctx.bezierCurveTo(rx,cy+ymagic,cx+xmagic,by,cx,by);
ctx.bezierCurveTo(cx-xmagic,by,lx,cy+ymagic,lx,cy);
ctx.bezierCurveTo(lx,cy-ymagic,cx-xmagic,ty,cx,ty);
ctx.fill();
ctx.stroke();
ctx.clip();
var text;
text = new fabric.Text('Honey', {
fontSize: 50,
left: 150,
top: 150,
lineHeight: 1,
originX: 'left',
fontFamily: 'Helvetica',
fontWeight: 'bold'
});
canvas.add(text);
Here is my fiddle link
You can see this output over here the line border of oval not much clear.
I am trying to draw a smooth oval using ctx.clip property in my canvas.I have done with drawing part i am facing problem with oval arc line clarity.Any one have any idea regarding this just let me know? Here is my code.
<canvas id="c" width="400" height="400"></canvas>
var canvas = new fabric.Canvas('c');
var ctx = canvas.getContext('2d');
var cx=180;
var cy=200;
var w=300;
var h=250;
// Quadratric curves example
ctx.beginPath();
var lx = cx - w/2,
rx = cx + w/2,
ty = cy - h/2,
by = cy + h/2;
var magic = 0.551784;
var xmagic = magic*w/2;
var ymagic = h*magic/2;
ctx.moveTo(cx,ty);
ctx.bezierCurveTo(cx+xmagic,ty,rx,cy-ymagic,rx,cy);
ctx.bezierCurveTo(rx,cy+ymagic,cx+xmagic,by,cx,by);
ctx.bezierCurveTo(cx-xmagic,by,lx,cy+ymagic,lx,cy);
ctx.bezierCurveTo(lx,cy-ymagic,cx-xmagic,ty,cx,ty);
ctx.fill();
ctx.stroke();
ctx.clip();
var text;
text = new fabric.Text('Honey', {
fontSize: 50,
left: 150,
top: 150,
lineHeight: 1,
originX: 'left',
fontFamily: 'Helvetica',
fontWeight: 'bold'
});
canvas.add(text);
Here is my fiddle link
You can see this output over here the line border of oval not much clear.
Share Improve this question edited Sep 28, 2013 at 13:56 Alex W 38.3k13 gold badges111 silver badges114 bronze badges asked Sep 28, 2013 at 13:37 Sanjay NakateSanjay Nakate 2,0986 gold badges43 silver badges77 bronze badges 2- 2 A one pixel line is not going to be very clear, you'd have to anti-alias it – Ruan Mendes Commented Sep 28, 2013 at 13:54
- what exacly @JuanMendes – Sanjay Nakate Commented Sep 28, 2013 at 13:55
5 Answers
Reset to default 3try this it will help you //Script
var canvas = new fabric.Canvas('c');
var w;
var h;
var ctx = canvas.getContext('2d');
w=canvas.width / 4;
h=canvas.height / 2.4;
canvas.clipTo = function(ctx) {
ctx.save();
ctx.scale(2, 1.2);
ctx.arc(w, h, 90, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.restore();
}
Fiddle Demo
One problem is in the nature of your display screen...
Since pixels are rectangles and you're drawing a curve, your result will have "jaggies" as the curve tries to fit itself in rectangular spaces.
You can use an optical illusion to trick the eye into seeing a less jagged oval.
An optical trick:
Reduce the contrast between the background color and the oval color.
This is not a cure...the jaggies are still there.
But the eye recognizes less contrast and perceives the oval as more smooth.
So if your design acmodates this style change, this optical illusion might help.
Here's code and a Fiddle: http://jsfiddle/m1erickson/vDWR3/
var cx=180;
var cy=200;
var w=300;
var h=250;
// Start with a less-contrasting background
ctx.fillStyle="#ddd";
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
var lx = cx - w/2,
rx = cx + w/2,
ty = cy - h/2,
by = cy + h/2;
var magic = 0.551784;
var xmagic = magic*w/2;
var ymagic = h*magic/2;
ctx.moveTo(cx,ty);
ctx.bezierCurveTo(cx+xmagic,ty,rx,cy-ymagic,rx,cy);
ctx.bezierCurveTo(rx,cy+ymagic,cx+xmagic,by,cx,by);
ctx.bezierCurveTo(cx-xmagic,by,lx,cy+ymagic,lx,cy);
ctx.bezierCurveTo(lx,cy-ymagic,cx-xmagic,ty,cx,ty);
ctx.fillStyle="#555";
ctx.strokeStyle=ctx.fillStyle;
ctx.lineWidth=1.5;
ctx.stroke();
Here is another alternative routine, but it looks visually the same as the other methods. This is primarily to do with the finite resolution of the display device, though you may be able to make some improvement using a thicker pencil, optical illusions or performing some anti-aliasing. Otherwise I think you will have to accept what you have.
Javascript
var canvas = new fabric.Canvas('c'),
ctx = canvas.getContext("2d"),
steps = 100,
step = 2 * Math.PI / steps,
h = 200,
k = 180,
r = 150,
factor = 0.8,
theta,
x,
y,
text;
ctx.beginPath();
for (theta = 0; theta < 2 * Math.PI; theta += step) {
x = h + r * Math.cos(theta);
y = k - factor * r * Math.sin(theta);
ctx.lineTo(x, y);
}
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.clip();
text = new fabric.Text('Honey', {
fontSize: 50,
left: 150,
top: 150,
lineHeight: 1,
originX: 'left',
fontFamily: 'Helvetica',
fontWeight: 'bold'
});
canvas.add(text);
jsfiddle
Note: by changing the number of steps and the factor, you can create other shapes: circles, squares, hexagons, other polygons ....
<canvas id="thecanvas" width="400" height="400"></canvas>
<script>
var canvas = document.getElementById('thecanvas');
if(canvas.getContext)
{
var ctx = canvas.getContext('2d');
drawEllipse(ctx, 10, 10, 100, 60);
drawEllipseByCenter(ctx, 60,40,20,10);
}
function drawEllipseByCenter(ctx, cx, cy, w, h) {
drawEllipse(ctx, cx - w/2.0, cy - h/2.0, w, h);
}
function drawEllipse(ctx, x, y, w, h) {
var kappa = .5522848,
ox = (w / 2) * kappa, // control point offset horizontal
oy = (h / 2) * kappa, // control point offset vertical
xe = x + w, // x-end
ye = y + h, // y-end
xm = x + w / 2, // x-middle
ym = y + h / 2; // y-middle
ctx.beginPath();
ctx.moveTo(x, ym);
ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
ctx.closePath();
ctx.stroke();
}
</script>
http://jsbin./ovuret/2/edit
A possibility is to use a thicker line, it's not great but it's better
ctx.lineWidth = 3;
http://jsfiddle/xadqg/7/
I also noticed that using quadraticCurveTo
seems to anti alias the line http://jsfiddle/d4JJ8/298/ I didn't change your code to use it but the jsfiddle I posted shows that it's true. You should modify your code and try it