亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > HTML > 正文

html5 Canvas畫圖教程(11)―使用lineTo/arc/bezierCurveTo畫橢圓形

2024-08-26 00:14:58
字體:
來源:轉載
供稿:網友
在canvas中可以很方便的用arc方法畫出圓形,本來圓形也可以看作是一個寬高相等的橢圓,但canvas中根本沒有畫橢圓的方法,我們要用其他方法來模擬。
我們首先要明確畫一個橢圓需要那些參數,基本的幾何知識告訴我們,橢圓需要圓心坐標,寬度,高度——或者還有旋轉角度,不過這個可以暫時不要,旋轉是比較容易的。
1,使用lineTo畫橢圓
你沒有看錯,lineTo這樣一個純粹用來畫直線的方法居然可以用來畫橢圓?。康_實存在,不過寫法實在是有些不可思議:

復制代碼 代碼如下:www.CuoXIn.com

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畫圓,然后把他縮放成一個橢圓
這個方法的原文在此,核心函數如下:

復制代碼 代碼如下:www.CuoXIn.com

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的縮放??s放有水平和垂直兩個方向,代碼中把canvas水平方向放大了,而垂直方向不變,so,原來arc畫出的圓形就變成了一個橢圓。
這個方法初看甚妙,代碼少,而且原理淺顯易懂。但分析一下就能發現他的明顯缺點了,就是——不精確!比如我需要寬171高56的橢圓,此時我們如果把arc的半徑定為28的話,那么后面就要為171/28/2這個蛋疼的不知所云的數字郁悶了。

不過有個折中的辦法是始終把arc的半徑設成100,然后,不夠就放大,超過了就縮小。但是,還是不精確。
3,使用貝賽爾曲線bezierCurveTo
自從覺得上面的縮放法不精確后,我就很想找到一個精確的畫橢圓的方法,最后在stackoverflow上找到了:

復制代碼 代碼如下:www.CuoXIn.com

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的帳號去提問,由于問題里有圖片,積分不夠不能傳,我還迫不得已用勉勉強強的英語水平去回答老外的問題掙積分。但最終好運到了,回答一個問題就解決了我的積分問題。
我提的貝賽爾曲線和橢圓的關系的問題在此.
說實話,下面老外的回答我大部分沒看懂,但幸虧他提供了一個代碼示例頁,讓我明白了原理,在此對他表示再次的感謝。而根據他的解答,我找到的畫橢圓的方法如下:

復制代碼 代碼如下:www.CuoXIn.com

//橢圓
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個方法畫出橢圓。
如果你發現了更簡單的方法,也請分享出來大家探討吧。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产亚洲精品高潮| 国产福利精品av综合导导航| 日韩视频永久免费观看| 国产91精品网站| 97在线观看免费| 清纯唯美亚洲激情| 97香蕉久久夜色精品国产| 欧美亚洲伦理www| 久久久久久久久久久免费精品| 久久全国免费视频| 91福利视频在线观看| 亚洲色图15p| 欧美华人在线视频| 久久精品亚洲国产| 国产伦精品一区二区三区精品视频| 午夜美女久久久久爽久久| 欧美与欧洲交xxxx免费观看| 久久久久久91| 亚洲一区二区少妇| 欧美日韩国产综合新一区| 丰满岳妇乱一区二区三区| 亚洲老板91色精品久久| 亚洲欧美国产一区二区三区| 欧美日本亚洲视频| xx视频.9999.com| 欧美激情精品久久久久| 亚洲精品永久免费精品| 亚洲国产欧美一区二区三区同亚洲| 欧美最猛性xxxxx亚洲精品| 色久欧美在线视频观看| 日韩精品中文字幕在线| 国产99久久精品一区二区 夜夜躁日日躁| 国产精品成人一区| 欧美一区二区三区图| 在线视频日本亚洲性| 成人免费观看网址| 成人激情视频网| 欧美日韩成人黄色| 性欧美xxxx视频在线观看| 欧美电影免费观看大全| 国产69精品久久久久9| 国产精品色悠悠| 国产v综合v亚洲欧美久久| 亚洲新中文字幕| 97视频免费看| 不卡av电影在线观看| 亚洲美女视频网站| 97久久久免费福利网址| 欧美理论电影在线观看| 国产精品欧美日韩一区二区| 中文字幕亚洲无线码a| 亚洲午夜国产成人av电影男同| 午夜精品久久久久久久男人的天堂| 欧美激情高清视频| 久久久久久久香蕉网| 欧美成人sm免费视频| 国产在线拍偷自揄拍精品| 国产精品视频午夜| 久久久久久香蕉网| 国产精品久久久久久婷婷天堂| 欧美视频在线免费看| 狠狠躁夜夜躁人人爽超碰91| 国产在线播放不卡| 中文字幕精品在线视频| 亚洲成人av中文字幕| 欧美专区在线播放| 欧美亚洲视频在线观看| 国产男人精品视频| 亚洲成色777777女色窝| 国产精品高清网站| 777777777亚洲妇女| 欧美乱妇高清无乱码| 国产精品亚洲欧美导航| 欧美人与物videos| 九九久久精品一区| 国内揄拍国内精品少妇国语| 97国产精品视频人人做人人爱| 国产精品免费看久久久香蕉| 亚洲男人天堂视频| 国产成人精品一区二区| 成人激情黄色网| 亚洲欧美激情另类校园| 日韩成人av网| 97国产一区二区精品久久呦| 精品香蕉在线观看视频一| 国产午夜精品理论片a级探花| 国产福利精品av综合导导航| 国产亚洲人成a一在线v站| 欧美一区二区大胆人体摄影专业网站| 欧美美女15p| 精品视频久久久久久久| 亚洲韩国欧洲国产日产av| 在线播放国产精品| 91亚洲一区精品| 欧美日韩中文字幕综合视频| 亚洲va欧美va国产综合剧情| 综合网日日天干夜夜久久| 色播久久人人爽人人爽人人片视av| 亚洲第一av网| 国产精品久久一区| 国产精品久久久久久久app| 亚洲精品资源美女情侣酒店| 欧美极品xxxx| 亚洲一区二区自拍| 一区二区三区视频免费在线观看| 美日韩精品免费视频| 日韩欧美在线看| 久久精品中文字幕电影| 国产精品尤物福利片在线观看| 在线观看免费高清视频97| 精品日韩中文字幕| 北条麻妃在线一区二区| 亚洲免费视频观看| 国模极品一区二区三区| 亚洲va久久久噜噜噜久久天堂| 日韩中文字幕在线观看| 69精品小视频| 亚洲成人久久久| 5566成人精品视频免费| 国产性色av一区二区| 欧美激情三级免费| 中文字幕日韩精品在线| 在线精品播放av| 日韩美女在线看| www.99久久热国产日韩欧美.com| 69av在线播放| 久久影视电视剧免费网站清宫辞电视| 91在线国产电影| 亚洲成人aaa| 中文字幕日韩在线播放| 欧美激情视频在线观看| 久久久久久久影院| 欧美福利视频网站| 亚洲性视频网站| 日韩av中文字幕在线| 久久不射热爱视频精品| 国产精品扒开腿做爽爽爽视频| 欧美一级片免费在线| 亚洲电影在线看| 狠狠色噜噜狠狠狠狠97| 成人久久一区二区| 国产精品video| 久久人人爽人人爽人人片av高请| 午夜精品在线观看| 免费97视频在线精品国自产拍| 午夜欧美不卡精品aaaaa| 在线视频亚洲欧美| 7777免费精品视频| 人人做人人澡人人爽欧美| 欧美成人三级视频网站| 日本精品一区二区三区在线| 亚洲亚裔videos黑人hd| 日韩在线观看免费高清完整版| 538国产精品一区二区在线| 国产成人在线亚洲欧美| 国产精品永久免费视频| 日本乱人伦a精品| 欧美激情视频在线免费观看 欧美视频免费一| 1769国内精品视频在线播放| 精品亚洲国产成av人片传媒| 国产精品999999| 国产精品久久久久福利| 91超碰caoporn97人人| 国产精品福利在线|