Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/466.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在画布上绘制平滑的椭圆形_Javascript_Css_Html_Canvas_Fabricjs - Fatal编程技术网

Javascript 如何在画布上绘制平滑的椭圆形

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

我正在尝试在画布中使用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;
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();
}