Rumah  >  Artikel  >  hujung hadapan web  >  html5 Tutorial lukisan kanvas (11)—Gunakan lineTo/arc/bezierCurveTo untuk melukis kemahiran tutorial oval_html5

html5 Tutorial lukisan kanvas (11)—Gunakan lineTo/arc/bezierCurveTo untuk melukis kemahiran tutorial oval_html5

WBOY
WBOYasal
2016-05-16 15:50:051601semak imbas

Dalam kanvas, anda boleh menggunakan kaedah arka untuk melukis bulatan Pada asalnya, bulatan juga boleh dianggap sebagai elips dengan lebar dan ketinggian yang sama, tetapi tidak ada cara untuk melukis elips dalam kanvas untuk mensimulasikannya.
Kita mesti terlebih dahulu menjelaskan parameter yang diperlukan untuk melukis elips Pengetahuan geometri asas memberitahu kita bahawa elips memerlukan koordinat pusat, lebar, ketinggian - atau sudut putaran, tetapi ini boleh diabaikan buat masa ini, putaran lebih mudah.
1. Gunakan lineTo untuk melukis elips
Anda membaca betul, lineTo, kaedah yang digunakan untuk melukis garis lurus, sebenarnya boleh digunakan untuk melukis elips! ? Tetapi dia memang wujud, tetapi kaedah penulisannya sungguh luar biasa:

Salin kod
Kodnya adalah seperti berikut:

fungsi DrawEllipse(Kanvas,O,OA,OB){
//Lukis elips, contoh: var B=New Array(150,150); ;
dengan ( Kanvas){
var x=O[0] OA; 0;i<=360 ;i ){
var ii=i*Math.PI/180;
var x=O[0] OA*Math.cos(ii); [1]-OB* Math.sin(ii);
lineTo(x,y);
}
}
}


Prinsip kaedah ini ialah bahawa bulatan mempunyai 360 darjah, Kemudian gunakan lineTo untuk menggelung 360 kali, lukis segmen garisan untuk setiap darjah, dan akhirnya sambungkannya menjadi elips. Fungsi trigonometri sinus dan kosinus diperlukan untuk pengiraan.
Perhatikan bahawa parameter kedua kaedah ini ialah tatasusunan, iaitu koordinat tengah elips
Ideanya sangat pelik, dan elips yang dilukis agak lancar. Tetapi ia tidak berbaloi untuk digunakan untuk semua orang - kaedah ini akan berkitar 360 kali setiap kali ia melukis elips, dan hanya melukis lebih banyak elips, yang merupakan ujian untuk prestasi penyemak imbas.
Kita hanya perlu memahami ideanya

2 Gunakan lengkok untuk melukis bulatan, dan kemudian skalakannya menjadi elips

Teks asal kaedah ini ada di sini, dan intinya. fungsi adalah seperti berikut:



Salin kod
Kod adalah seperti berikut: var canvas = document.getElementById('myCanvas ');
// save state
context.save();
// terjemah konteks
context.translate(canvas.width / 2, canvas.height / 2); secara mendatar
context.scale( 2, 1);
// lukis bulatan yang akan diregangkan menjadi
context.beginPath();
context.arc(centerX, centerY, radius, 0 , 2 * Math.PI, false );
// pulihkan kepada keadaan asal
context.restore()


Kaedah ini menggunakan fungsi kanvas yang tidak pernah saya bincangkan sebelum ini , iaitu skala, yang boleh melaksanakan kanvas zum. Terdapat dua arah penskalaan: mendatar dan menegak Dalam kod, kanvas dibesarkan dalam arah mendatar, tetapi arah menegak kekal tidak berubah Jadi, bulatan yang dilukis dengan lengkok menjadi elips.
Kaedah ini kelihatan sangat baik pada pandangan pertama, dengan kurang kod dan prinsipnya mudah difahami. Tetapi selepas analisis, anda boleh menemui kelemahannya yang jelas, iaitu - ketidaktepatan! Sebagai contoh, saya memerlukan elips dengan lebar 171 dan ketinggian 56. Jika kita menetapkan jejari arka kepada 28, maka kita akan tertekan oleh nombor yang menyakitkan dan tidak dapat difahami 171/28/2.

Tetapi kompromi adalah dengan sentiasa menetapkan jejari arka kepada 100, dan kemudian besarkan jika tidak mencukupi, dan kecilkan jika melebihinya. Walau bagaimanapun, ia masih tidak tepat.

3, gunakan Bezier curve bezierCurveTo

Memandangkan saya merasakan kaedah penskalaan di atas tidak tepat, saya ingin mencari kaedah yang tepat untuk melukis elips, dan akhirnya menemuinya pada stackoverflow:





Salin kod
Kod adalah seperti berikut:

function drawEllipse(ctx, x, y , w, h) {
var kappa = 0.5522848; ox = (w / 2) * kappa, // titik kawalan mengimbangi mendatar oy = (h / 2) * kappa, // titik kawalan mengimbangi menegak xe = x w, // x-hujung ye = y h, // y-hujung
xm = x w / 2, // x-tengah
ym = y h / 2; / y-tengah
ctx.beginPath();
ctx.moveTo(x, ym);
ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); 🎜 >ctx.bezierCurveTo(xm lembu, y, xe, ym - oy, xe, ym);
ctx.bezierCurveTo(xe, ym oy, xm ox, ye, xm, ye); ( xm - ox, ye, x, ym oy, x, ym);
Kaedah ini boleh dianggap sempurna. Dia membahagikan elips kepada empat lengkung Bezier dan menyambungkannya untuk membentuk elips. Akhirnya, lebar dan tinggi adalah lebih tepat dan overhed adalah kurang.
Tetapi kaedah ini masih mempunyai kekurangan. Lihat pada parameter kappa, ia mempunyai nilai yang sangat pelik. Saya percaya ramai orang tidak faham mengapa ia perlu menjadi nilai ini sehingga pakar geometri memberitahu anda mengapa ia perlu menjadi nilai ini - saya masih tidak tahu. Dan saya mempunyai keinginan yang kuat untuk mengubahnya dan melihat apa akibatnya.

Sudah tentu, impuls saya yang serupa dengan pesakit gangguan obsesif-kompulsif tidak boleh dikatakan sebagai kelemahan kaedah ini. Saya secara peribadi merasakan bahawa elips jelas terdiri daripada dua lengkung Bezier dan bukannya empat. Idea ini akhirnya membawa saya kepada cara yang sempurna untuk melukis elips.
4, gunakan dua lengkung Bezier untuk melukis elips
Untuk memahami sama ada kaedah sebelumnya boleh dipermudahkan, saya telah mendaftarkan akaun stackoverflow untuk bertanyakan soalan soalan, saya tidak mempunyai mata yang mencukupi untuk dipindahkan, jadi saya terpaksa menggunakan bahasa Inggeris saya yang hampir tidak mencukupi untuk menjawab soalan daripada orang asing untuk mendapatkan mata. Tetapi nasib akhirnya datang dan masalah mata saya diselesaikan dengan menjawab soalan.
Soalan yang saya tanya tentang hubungan antara lengkung Bezier dan elips ada di sini
Sejujurnya, saya tidak faham kebanyakan jawapan orang asing di bawah, tetapi mujurlah dia menyediakan halaman contoh kod, yang membuatkan saya faham. . Prinsip, saya ingin mengucapkan terima kasih kepada beliau sekali lagi. Mengikut jawapan beliau, kaedah yang saya dapati untuk melukis elips adalah seperti berikut:

Salin kod
Kodnya ialah seperti berikut:

//Ellipse
CanvasRenderingContext2D.prototype.oval = fungsi (x, y, lebar, tinggi) {
var k = (lebar/0.75)/2,
w = lebar/ 2,
h = tinggi/2;
this.beginPath();
this.moveTo(x, y-h); , y h, x, y h );
ini.bezierCurveTo(x-k, y h, x-k, y-h, x, y-h);

Kaedah ini tepat, memerlukan kod yang lebih sedikit dan tidak mempunyai sebarang ciri pelik. Ingat ini, nisbah lebar elips kepada koordinat titik kawalan lengkung Bezier yang melukis elips adalah seperti berikut:
Titik kawalan Bezier x=(lebar elips/0.75)/2 Ini sudah dalam kod yang ditunjukkan dalam.

Anda boleh mencuba 4 kaedah di atas untuk melukis elips.
Jika anda menemui kaedah yang lebih mudah, sila kongsikan dengan kami untuk perbincangan.
Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn