Di kanvas, Anda dapat dengan mudah menggambar lingkaran menggunakan metode busur. Awalnya, lingkaran juga dapat dianggap sebagai elips dengan lebar dan tinggi yang sama, tetapi tidak ada cara untuk menggambar elips di kanvas. Kita perlu menggunakan metode lain untuk mensimulasikannya.
Pertama -tama, kita perlu mengklarifikasi parameter yang diperlukan untuk menggambar elips. Pengetahuan geometris dasar memberi tahu kita bahwa elips membutuhkan koordinat pusat, lebar, tinggi, atau sudut rotasi, tetapi ini dapat dihindari untuk saat ini, rotasi relatif mudah.
1. Gunakan lineto untuk menggambar elips Anda membaca benar, Lineto, metode yang murni digunakan untuk menggambar garis lurus, sebenarnya dapat digunakan untuk menggambar elips! ? Tapi dia memang ada, tetapi gaya penulisannya benar -benar luar biasa:Function Drawellipse (Canvas, O, OA, OB) {
// Gambar elips, contoh: var b = array baru (150.150); Drawellipse (HB, B, 50,30);
dengan (kanvas) {
var x = o [0]+oa;
var y = o [1];
moveto (x, y);
untuk (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);
}
}
}
Prinsip metode ini adalah bahwa lingkaran memiliki 360 derajat, jadi gunakan lineto untuk melingkar 360 kali, menggambar segmen garis dari setiap derajat, dan akhirnya menghubungkannya ke elips. Di antara mereka, fungsi cosinus sinus trigonometri perlu digunakan untuk perhitungan.
Perhatikan bahwa parameter kedua dari metode ini adalah array, yaitu, koordinat pusat elips.
Idenya sangat aneh, dan elips yang ditarik relatif halus. Tetapi tidak layak digunakan - metode ini membutuhkan 360 siklus untuk setiap elips yang ditarik. Hanya ketika elips ditarik adalah tes sekecil apa pun dari kinerja browser.
Kita hanya perlu memahami idenya
2. Gunakan busur untuk menggambar lingkaran dan skala menjadi elips Teks asli dari metode ini ada di sini, dan fungsi inti adalah sebagai berikut:var canvas = document.geteLementById ('myCanvas');
var context = canvas.getContext ('2d');
var centerx = 0;
var centery = 0;
var radius = 50;
// simpan status
Context.Save ();
// Terjemahkan konteks
context.translate (canvas.width / 2, canvas.height / 2);
// skala konteks secara horizontal
Context.Scale (2, 1);
// Gambar lingkaran yang akan diregangkan menjadi oval
context.beginpath ();
Context.arc (Centre, Centery, Radius, 0, 2 * Math.pi, false);
// Kembalikan ke keadaan asli
Context.Restore ()
Metode ini menggunakan fungsi kanvas yang belum saya sebutkan sebelumnya, yaitu, skala, yang dapat mewujudkan penskalaan kanvas. Penskalaan memiliki dua arah: horizontal dan vertikal. Kode memperbesar arah horizontal kanvas, sedangkan arah vertikal tetap tidak berubah. Jadi, lingkaran yang digambar oleh busur berubah menjadi elips.
Metode ini sangat indah pada pandangan pertama, dengan beberapa kode, dan prinsip -prinsipnya sederhana dan mudah dimengerti. Tetapi setelah menganalisisnya, Anda akan menemukan kekurangannya yang jelas, yaitu - tidak akurat! Misalnya, saya membutuhkan elips yang lebar 171 dan tinggi. Jika kita mengatur jari -jari busur ke 28, maka jumlah berikutnya 171/28/2 akan tertekan.
Namun, ada metode kompromi untuk selalu mengatur jari -jari busur ke 100, dan kemudian, jika tidak cukup, itu akan diperbesar, dan jika melebihi, itu akan dikurangi. Namun, itu masih tidak akurat.
3. Gunakan Bezier Curveto Karena saya merasa bahwa metode penskalaan di atas tidak akurat, saya benar -benar ingin menemukan metode yang tepat untuk menggambar elips, dan akhirnya menemukannya di stackoverflow:function drawellipse (ctx, x, y, w, h) {
var kappa = 0,5522848;
OX = (w / 2) * kappa, // titik kontrol offset horizontal
oy = (h / 2) * kappa, // titik kontrol offset vertikal
xe = x + w, // x-end
kamu = 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 ();
}
Metode ini dapat dianggap sempurna. Dia membagi elips menjadi 4 kurva bezier dan menghubungkannya ke elips. Lebar dan tinggi akhir juga relatif akurat dan overhead lebih sedikit.
Tetapi metode ini masih memiliki kelemahannya. Semua orang melihat parameter Kappa, dan ada nilai yang sangat aneh. Saya percaya bahwa banyak orang tidak mengerti mengapa mereka harus mengambil nilai ini sebelum ahli geometri memberi tahu Anda mengapa mereka ingin mengambil nilai ini - saya masih tidak mengetahuinya. Dan saya memiliki keinginan kuat untuk mengubahnya dan melihat apa konsekuensinya.
Tentu saja, impuls saya mirip dengan pasien gangguan obsesif-kompulsif tidak dapat dikatakan sebagai kerugian dari metode ini. Kerugiannya yang sebenarnya adalah - mengapa Anda perlu menggunakan 4 kurva bezier? Saya pribadi berpikir bahwa elips jelas terdiri dari dua kurva bezier daripada empat. Gagasan ini akhirnya membuat saya menemukan cara paling sempurna untuk menggambar elips.
4. Gunakan dua kurva Besel untuk menggambar elips
Untuk memahami apakah metode sebelumnya dapat disederhanakan, saya secara khusus mendaftarkan akun stackoverflow untuk mengajukan pertanyaan. Karena ada gambar dalam pertanyaan, poin tidak dapat ditransmisikan. Saya harus menggunakan kemahiran saya yang nyaris tidak berbahasa Inggris untuk menjawab pertanyaan orang asing untuk mendapatkan poin. Tetapi pada akhirnya, semoga berhasil datang, dan menjawab pertanyaan memecahkan masalah poin saya.
Saya telah mengangkat masalah hubungan antara Besel Curve dan Ellipse.
Sejujurnya, saya tidak memahami sebagian besar jawaban orang asing di bawah ini, tetapi untungnya dia memberikan halaman sampel kode, yang membuat saya memahami prinsipnya, dan saya ingin mengucapkan terima kasih lagi. Menurut jawabannya, metode yang saya temukan untuk menggambar elips adalah sebagai berikut:
//bulat telur
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, yh);
this.beziercurveto (x+k, yh, x+k, y+h, x, y+h);
this.beziercurveto (xk, y+h, xk, yh, x, yh);
this.closepath ();
kembalikan ini;
}
Metode ini akurat dan memiliki sedikit kode, dan tidak ada yang aneh dan sulit untuk dipahami. Ingat saja ini, rasio koordinat dari lebar elips ke titik kontrol kurva Besel yang menarik elips adalah sebagai berikut:
Titik kontrol Bessel x = (lebar elips/0,75)/2 sudah tercermin dalam kode.
Anda dapat menguji empat metode di atas untuk menggambar elips.
Jika Anda menemukan cara yang lebih mudah, silakan bagikan dan diskusikan.