Javascript 如何在画布上绘制平滑的椭圆形
我正在尝试在画布中使用ctx.clip属性绘制一个平滑的椭圆形。我已经完成了绘制部分,我面临椭圆形弧线清晰度的问题。有人对此有任何想法,请告诉我? 这是我的密码Javascript 如何在画布上绘制平滑的椭圆形,javascript,css,html,canvas,fabricjs,Javascript,Css,Html,Canvas,Fabricjs,我正在尝试在画布中使用ctx.clip属性绘制一个平滑的椭圆形。我已经完成了绘制部分,我面临椭圆形弧线清晰度的问题。有人对此有任何想法,请告诉我? 这是我的密码 <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
<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);
var canvas=newfabric.canvas('c');
var ctx=canvas.getContext('2d');
var-cx=180;
var-cy=200;
var w=300;
var h=250;
//二次曲线示例
ctx.beginPath();
变量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);
cx.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('Honey'{
尺寸:50,
左:150,
排名:150,
线宽:1,
原文:“左”,
fontFamily:“Helvetica”,
fontWeight:“粗体”
});
canvas.add(文本);
你可以在这里看到这个输出,椭圆的线边界不太清晰。
var canvas=document.getElementById('thecanvas');
if(canvas.getContext)
{
var ctx=canvas.getContext('2d');
抽屉式(ctx,10,10,100,60);
抽屉式电子秤(ctx,60,40,20,10);
}
功能抽屉式电子显示屏中心(ctx、cx、cy、w、h){
抽屉(ctx,cx-w/2.0,cy-h/2.0,w,h);
}
功能抽屉(ctx、x、y、w、h){
var kappa=.5522848,
ox=(w/2)*卡帕,//控制点偏移水平
oy=(h/2)*卡帕,//控制点垂直偏移
xe=x+w,//x-end
ye=y+h,//y端
xm=x+w/2,//x-middle
ym=y+h/2;//y-中间
ctx.beginPath();
ctx.moveTo(x,ym);
贝塞尔曲线(x,ym-oy,xm-ox,y,xm,y);
贝塞尔曲线(xm+ox,y,xe,ym-oy,xe,ym);
ctx.bezierCurveTo(xe,ym+oy,xm+ox,ye,xm,ye);
贝塞尔曲线(xm-ox,ye,x,ym+oy,x,ym);
ctx.closePath();
ctx.stroke();
}
一种可能性是使用较粗的线条,它不是很好,但更好
ctx.lineWidth = 3;
我还注意到,使用
quadraticCurveTo
似乎可以消除这一行的别名,我没有更改代码以使用它,但我发布的JSFIDLE表明这是正确的。您应该修改代码并试用它一个问题是显示屏的性质…
由于像素是矩形,并且您正在绘制一条曲线,因此当曲线试图在矩形空间中拟合时,结果将出现“锯齿”
你可以用一种视觉错觉来欺骗眼睛,使其看到一个不那么参差不齐的椭圆形
光学技巧:
降低背景色和椭圆形之间的对比度
这不是治疗方法…锯齿还在那里
但是眼睛识别的对比度较低,感觉椭圆形更光滑
因此,如果你的设计适应了这种风格的变化,这种视觉错觉可能会有所帮助
下面是代码和小提琴:
这里是另一个可选例程,但它在视觉上与其他方法相同。这主要与显示设备的有限分辨率有关,尽管您可以使用较厚的铅笔、光学错觉或执行一些抗锯齿来进行一些改进。否则我认为你将不得不接受你所拥有的 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);
var canvas=newfabric.canvas('c'),
ctx=canvas.getContext(“2d”),
步数=100,
步骤=2*Math.PI/步骤,
h=200,
k=180,
r=150,
系数=0.8,
西塔,
x,,
Y
文本;
ctx.beginPath();
对于(θ=0;θ<2*Math.PI;θ+=步长){
x=h+r*数学cos(θ);
y=k-因子*r*Math.sin(θ);
ctx.lineTo(x,y);
}
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.clip();
text=新结构。text('Honey'{
尺寸:50,
左:150,
排名:150,
线宽:1,
原文:“左”,
fontFamily:“Helvetica”,
fontWeight:“粗体”
});
canvas.add(文本);
注意:通过更改步数和因子,您可以创建其他形状:圆、正方形、六边形、其他多边形……试试这个,它会对您有所帮助
//剧本
Fiddle当我将其集成到我的代码检查抗锯齿方法中时,这也不是很清楚,看不出有太大的差异。一个像素线不会很清楚,你必须用反别名,比如@JuanMendesI看到的,但当我选择文本时,它又变得不清晰了。@SanjayNakate我看不出你在观察什么,当我选择文本时它看起来完全一样(用Chrome),我认为粗一点的铅笔就很简单,也很好+1在chrome中,它工作得有点好,我希望你对Mozilla@JuanMendes+1的问题没有意见,这里有一个变量,它允许指定x和y半径:@Ken,它似乎提供了一个很好的抗锯齿效果。@Ken我注意到它看起来和所有其他方法一样
ctx.clip()
是在不知道结构的情况下调用的,我假设它使用双分辨率方法。只需将线宽增加到1.5或2即可进行补偿。问题是,双分辨率将以一半的大小绘制到主画布上,这也会降低抗锯齿效果。是的,我仍然认为,更粗的笔是解决OPs问题的最佳方法。
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();
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);
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();
}