Reputation: 2098
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);
You can see this output over here the line border of oval not much clear.
Upvotes: 5
Views: 2492
Reputation: 1330
try 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
Upvotes: 3
Reputation: 23482
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);
Note: by changing the number of steps and the factor, you can create other shapes: circles, squares, hexagons, other polygons ....
Upvotes: 1
Reputation: 105015
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 accommodates this style change, this optical illusion might help.
Here's code and a Fiddle: http://jsfiddle.net/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();
Upvotes: 2
Reputation: 92274
A possibility is to use a thicker line, it's not great but it's better
ctx.lineWidth = 3;
I also noticed that using quadraticCurveTo
seems to anti alias the line http://jsfiddle.net/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
Upvotes: 0
Reputation: 1259
<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.com/ovuret/2/edit
Upvotes: 0