加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

html5 Canvas绘图教程(11)—行使lineTo/arc/bezierCurveTo画椭圆形

发布时间:2020-09-21 06:36:53 所属栏目:编程 来源:网络整理
导读:canvas中基础没有画椭圆的要领,我们要用其他要领来模仿,我们起主要明晰画一个椭圆必要那些参数,根基的几许常识汇报我们,椭圆必要圆心坐标,宽度,高度——或
在canvas中可以很利便的用arc要领画出圆形,原来圆形也可以看作是一个宽高相称的椭圆,但canvas中基础没有画椭圆的要领,我们要用其他要领来模仿。
我们起主要明晰画一个椭圆必要那些参数,根基的几许常识汇报我们,椭圆必要圆心坐标,宽度,高度——可能尚有旋转角度,不外这个可以暂且不要,旋转是较量轻易的。
1,行使lineTo画椭圆
你没有看错,lineTo这样一个纯粹用来画直线的要领居然可以用来画椭圆!?但他确实存在,不外写法其实是有些不行思议:

复制代码

代码如下:


function DrawEllipse(Canvas,O,OA,OB){
//画椭圆,例子:var B=new Array(150,150); DrawEllipse(hb,B,50,30);
with (Canvas){
var x=O[0]+OA;
var y=O[1];
moveTo(x,y);
for (var i=0;i<=360;i++){
var ii=i*Math.PI/180;
var x=O[0]+OA*Math.cos(ii);
var y=O[1]-OB*Math.sin(ii);
lineTo(x,y);
}
}
}


这个要领的道理是,一个圆有360度,那么就用lineTo轮回360次,画出每一度的线段,最终连成一个椭圆。个中必要用到三角函数正弦余弦举办计较。
留意,这个要领的第2个参数是个数组,即椭圆的圆心坐标.

思绪很奇葩,并且画出的椭圆也较量滑腻。但不值得各人行使——此要领每画一个椭圆,就要轮回360次,只有画的椭圆轻微一多,对赏识器的机能就是个检验。
我们只用相识一下他的思绪即可
2,行使arc画圆,然后把他缩放成一个椭圆
这个要领的原文在此,焦点函数如下:

复制代码

代码如下:


var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = 0;
var centerY = 0;
var radius = 50;
// save state
context.save();
// translate context
context.translate(canvas.width / 2, canvas.height / 2);
// scale context horizontally
context.scale(2, 1);
// draw circle which will be stretched into an oval
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// restore to original state
context.restore()


此要领用了一个我前面还没讲过的canvas函数,即scale,他能实现canvas的缩放。缩放有程度和垂直两个偏向,代码中把canvas程度偏向放大了,而垂直偏向稳固,so,原本arc画出的圆形就酿成了一个椭圆。
这个要领初看甚妙,代码少,并且道理浅近易懂。但说明一下就能发明他的明明弱点了,就是——不准确!好比我必要宽171高56的椭圆,此时我们假如把arc的半径定为28的话,那么后头就要为171/28/2这个蛋疼的不知所云的数字忧郁了。

不外有个折中的步伐是始终把arc的半径设成100,然后,不足就放大,高出了就缩小。可是,照旧不准确。
3,行使贝赛尔曲线bezierCurveTo
自从认为上面的缩放法不准确后,我就很想找到一个准确的画椭圆的要领,最后在stackoverflow上找到了:

复制代码

代码如下:


function drawEllipse(ctx, x, y, w, h) {
var kappa = 0.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();
}


这个要领可以算是较量美满的了。他把一个椭圆分成了4条贝塞尔曲线,用他们连成了一个椭圆。最后宽度高度也较量准确,开销也较少。
但此要领依然有弱点。各人看谁人kappa参数,有个很怪异的值,信托许多人在几许专家汇报你为什么他要取这个值之前,都不大白为什么非要取这个值——我到此刻照旧不知道。而且我有很凶猛的想把他改一下看看有什么效果的激动。

虽然我这种相同强制症患者的激动并不能说成是此要领的弱点,他真正的弱点是——为什么要用4条贝塞尔曲线?我小我私人认为,一个椭圆明明是由两条贝塞尔曲线构成的而不是4条。这个设法最终让我找到了最美满的画椭圆的要领。
 4,行使两条贝赛尔曲线画出椭圆
为了相识上一个要领可否精简,我专门注册了一个stackoverflow的帐号去提问,因为题目里有图片,积分不足不能传,我还必不得已用勉始末强的英语程度去答复老外的题目挣积分。但最终好运到了,答复一个题目就办理了我的积分题目。
我提的贝赛尔曲线和椭圆的相关的题目在此.
说真话,下面老外的答复我大部门没看懂,但好在他提供了一个代码示例页,让我大白了道理,在此对他暗示再次的感激。而按照他的解答,我找到的画椭圆的要领如下:

复制代码

代码如下:


//椭圆
CanvasRenderingContext2D.prototype.oval = function (x, y, width, height) {
var k = (width/0.75)/2,
w = width/2,
h = height/2;
this.beginPath();
this.moveTo(x, y-h);
this.bezierCurveTo(x+k, y-h, x+k, y+h, x, y+h);
this.bezierCurveTo(x-k, y+h, x-k, y-h, x, y-h);
this.closePath();
return this;
}


此要领既准确,又代码少,并且也没有稀疏的难解的处所。只必要记着这一点,椭圆的宽度与画出椭圆的贝赛尔曲线的节制点的坐标比譬喻下:
贝塞尔节制点x=(椭圆宽度/0.75)/2这一点已经在代码中浮现了。

各人可自行试验上面的4个要领画出椭圆。
假如你发明白更简朴的要领,也请分享出来各人切磋吧。

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读