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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。