canvas类中用于绘制椭圆形的方法为,html画椭圆

  canvas类中用于绘制椭圆形的方法为,html画椭圆

  概述

  HTML5中的Canvas并没有直接提供画椭圆的方法。下面总结几种画图方法。每种方法都有其优缺点,要根据情况选择。每种方法的参数都是相同的:

  1.1 .上下文是画布的2D绘图环境对象,

  2.x是椭圆中心的横坐标,

  3.y是椭圆中心的纵坐标,

  4.a是椭圆的横向半轴的长度,

  5.b是椭圆的纵向半轴长度。

  参数方程法

  该方法使用椭圆的参数方程绘制椭圆副本代码如下:

  //-

  //函数的参数x和y是椭圆的中心;a、b分别是椭圆形的横向半轴,

  //纵轴和半轴的长度不能同时为0。

  //这种方法的缺点是当线宽较宽而椭圆较平时

  //椭圆内长轴端尖锐,不光滑,效率低。

  函数ParamEllipse(上下文,x,y,a,b)

  {

  //max等于1除以长轴值A和b中的较大值。

  //i每循环增加1/max,表示度数增加。

  //这样可以使每个周期画出的路径(弧线)接近1个像素。

  var步长=(a b)?1/a:1/b;

  context . begin path();

  context.moveTo(x a,y);//从椭圆的左端点开始绘制

  for(var I=0;i 2 *数学。PI;i=步长)

  {

  //参数方程为x=a * cos(i),y=b * sin(i),

  //参数是I,表示度数(弧度)

  context.lineTo(x a * Math.cos(i),y b * math . sin(I));

  }

  context . close path();

  context . stroke();

  };

  均匀压缩法

  这种方法利用数学中的均匀压缩原理,将一个圆均匀压缩成一个椭圆。理论上可以得到一个标准的椭圆。下面的代码会有行宽不一致的问题。解决方法见5楼simonleung的评论。按如下方式复制代码:/pp//-

  //方法是用圆弧法画圆,结合比例尺。

  //在水平或垂直轴方向上缩放(均匀压缩)

  //用这种方法画出的椭圆,越靠近长轴的末端边缘越粗,长轴末端的线宽就是正常值。

  //边缘越靠近短轴,椭圆越平越细,甚至不连续,这是缩放的结果。

  //这个缺点有时候也是优点,比如在展示光环(行星光环)的立体效果时

  //当参数A或B为0时,此方法不适用

  函数EvenCompEllipse(上下文,x,y,a,b)

  {

  context . save();

  //选择A和B中较大的一个作为圆弧法的半径参数

  var r=(a b)?甲:乙;

  var ratio x=a/r;//水平轴缩放比例

  var ratio y=b/r;//垂直轴缩放比例

  context . scale(ratix,ratoy);//缩放(均匀压缩)

  context . begin path();

  //从椭圆的左端点逆时针绘制

  context . move to((x a)/ratix,y/ratioY);

  context.arc(x/ratioX,y/ratioY,r,0,2 * Math。PI);

  context . close path();

  context . stroke();

  context . restore();

  };

  三次贝塞尔曲线法一

  用三次Bezier曲线画出的椭圆,实际上是一种近似,理论上也是一种近似。但由于其效率高,所以在计算机矢量图形中常用来画椭圆,但具体的原理我就不知道了。近似程度取决于两个控制点位置的选择。这种方法的控制点位置是我自己实验得出的,精度还可以。复制代码如下:

  //-使用三次贝塞尔曲线模拟椭圆1。

  //当线宽较宽且椭圆较平时,此方法也会产生,

  //长轴端锋利不光滑。

  函数BezierEllipse1(上下文,x,y,a,b)

  {

  //关键是bezierCurveTo中两个控制点的设置。

  //0.5和0.6是两个关键系数(在该函数中实验获得)

  var ox=0.5 * a,

  oy=0.6 * b;/PP context . save();

  context.translate(x,y);

  context . begin path();

  //从椭圆纵轴的下端逆时针绘制

  context.moveTo(0,b);

  context.bezierCurveTo(ox,b,a,oy,a,0);

  context.bezierCurveTo(a,-oy,ox,-b,0,-b);

  context.bezierCurveTo(-ox,-b,-a,-oy,-a,0);

  context.bezierCurveTo(-a,oy,-ox,b,0,b);

  context . close path();

  context . stroke();

  context . restore();/PP };

  三次贝塞尔曲线法二

  这个方法是由StackOverFlow里的一个帖子的回复改过来的,准确率很高,也是常用的画椭圆的方法。复制代码如下:

  //-使用三次贝塞尔曲线模拟椭圆2。

  //当线宽较宽且椭圆较平时,此方法也会生成

  //,长轴锋利不光滑。

  //这种方法比之前的贝塞尔方法更精确,但效率略低。

  函数BezierEllipse2(ctx,x,y,a,b)

  {

  var k=.5522848,

  Ox=a * k,//水平控制点偏移量

  oy=b * k;//垂直控制点偏移量/PP CTX . begin path();

  //从椭圆的左端顺时针画四条三次贝塞尔曲线。

  ctx.moveTo(x - a,y);

  ctx.bezierCurveTo(x - a,y - oy,x - ox,y - b,x,y-b);

  ctx.bezierCurveTo(x ox,y - b,x a,y - oy,x a,y);

  ctx.bezierCurveTo(x a,y oy,x ox,y b,x,y b);

  ctx.bezierCurveTo(x - ox,y b,x - a,y oy,x - a,y);

  CTX . close path();

  CTX . stroke();

  };

  光栅法

  这种方法可以根据Canvas可以操作像素的特点,利用图形学中的基本算法来绘制椭圆。比如中点椭圆算法等。

  其中一个例子是园友“豆豆狗”的博文《HTML5 Canvas高级类中的点圆算法(一)3354光栅图形(一)》。这种方法简单、灵活、高效、准确,但要实现一个绘制椭圆的有用功能却很复杂。比如线宽变化时,算法更复杂。虽然是画圆的算法,但是画椭圆的算法差不多,可以参考一下。

  总结

  基本上所有的方法都达不到100%的准确率,因为显示器分辨率的限制。

  其实最好的方法应该是圆弧()比例()。画布绘图库KineticJS使用的就是这种方法。

  在其他绘图软件中,不像HTML5中的canvas,没有提供固有的arc() scale()方法。通常用贝塞尔曲线来模拟近似椭圆,不管有多少条贝塞尔曲线是近似的。要用贝塞尔曲线模拟椭圆,可以参考这个资料:用折线、二次或三次贝塞尔曲线画椭圆弧。

  由于arc() scale()是浏览器已经实现的一种方法,而且理论上精度最高,所以从效率、精度、易用性来说都是最好的。

  用arc() scale()绘制椭圆后,调用context.stroke()和context.restore()方法的顺序不同,结果会很有意思。通常应该在划()之前恢复()。

  Demo

  以下是除光栅法外的几种椭圆函数的演示。演示代码如下:复制代码如下:

  div id= CanvasWrap style= background:# fff;宽度:600px高度:600px边框:1px纯黑色;/div/ppscript type= text/JavaScript //![CDATA[

  var画布,

  语境;

  var div=document . getelementbyid( CanvasWrap );

  div . innerhtml=“”;

  canvas=document . createelement( canvas );

  canvas.style.width=600px

  canvas.style.height=600px

  画布.宽度=600;

  canvas.height=600

  context=canvas . get context( 2d );

  div.appendChild(画布);/pp函数execDraw()

  {

  //解决Chrome下线宽小于等于1的问题

  context.lineWidth=1.1

  context.strokeStyle=black

  ParamEllipse(上下文,130,80,50,50);//圆形

  ParamEllipse(上下文,130,80,100,20);//椭圆

  EvenCompEllipse(上下文,130,200,50,50);//圆形

  EvenCompEllipse(上下文,130,200,100,20);//椭圆

  BezierEllipse1(上下文,470,80,50,50);//圆形

  BezierEllipse1(上下文,470,80,100,20);//椭圆

  BezierEllipse2(上下文,470,200,50,50);//圆形

  BezierEllipse2(上下文,470,200,100,20);//椭圆

  //检测相似性(一致程度)

  ParamEllipse(上下文,300,450,250,50);

  context.strokeStyle= yellow

  BezierEllipse1(上下文,300,450,250,50);

  context.strokeStyle= blue

  BezierEllipse2(上下文,300,450,250,50);

  };/pp函数clearCavnas()

  {

  context.clearRect(0,0,600,600);

  };

  //]]/脚本/ppp

  button onclick= execDraw();type=button 执行/按钮

  button onclick= clear canvas();type=button 清理/按钮

  /p

  注意,要成功运行代码,需要支持HTML5的帆布的浏览器。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: