Kanvas di HTML5 tidak secara langsung menyediakan metode untuk menggambar elips. Berikut ini adalah ringkasan dari beberapa metode menggambar. Berbagai metode memiliki kelebihan dan kekurangannya sendiri, dan dipilih sesuai dengan situasinya. Parameter masing -masing metode sama:
Konteks adalah objek lingkungan gambar 2D Canvas,
X adalah koordinat horizontal dari pusat elips.
y adalah koordinat vertikal dari pusat elips.
A adalah panjang sumbu setengah horizontal dari elips.
B adalah panjang setengah sumbu vertikal elips.
Metode Persamaan ParameterMetode ini menggunakan persamaan parametrik elips untuk menggambar elips
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Parameter x dan y dari fungsi adalah pusat elips; A dan B adalah setengah sumbu horizontal dari elips, masing-masing
// Panjang setengah sumbu vertikal tidak bisa 0 pada saat yang sama
// Kerugian dari metode ini adalah bahwa ketika linwidth lebih lebar dan elips itu menyanjung
// ujung sumbu utama dari elips bagian dalam tajam, tidak halus, dan memiliki efisiensi rendah
Paramellipse fungsi (konteks, x, y, a, b)
{
// MAX adalah nilai sumbu utama yang lebih besar a dan b
// Saya meningkatkan 1/maks untuk setiap siklus, menunjukkan peningkatan derajat
// Ini akan membuat jalur (busur) ditarik di setiap loop mendekati 1 piksel
var step = (a> b)? 1 / a: 1 / b;
context.beginpath ();
context.moveto (x + a, y); // Gambar dari titik akhir kiri elips
untuk (var i = 0; i <2 * math.pi; i += langkah)
{
// Persamaan parameter adalah x = a * cos (i), y = b * sin (i),
// parameternya adalah i, menunjukkan derajat (radian)
context.lineto (x + a * math.cos (i), y + b * math.sin (i));
}
context.closepath ();
Context.stroke ();
};
Metode kompresi seragamMetode ini menggunakan prinsip kompresi seragam dalam matematika untuk secara seragam mengompres lingkaran menjadi elips, yang secara teoritis dapat memperoleh elips standar. Kode berikut akan memiliki masalah dengan lebar garis yang tidak konsisten. Solusinya adalah melihat komentar Simonleung di lantai 5.
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Metode ini adalah menggambar lingkaran menggunakan metode ARC dan menggabungkan skala untuk
// penskalaan dalam arah sumbu horizontal atau vertikal (bahkan kompresi)
// Tepi elips yang ditarik dalam metode ini menjadi lebih tebal karena tepi lebih dekat ke ujung sumbu utama, dan lebar garis ujung sumbu utama adalah normal
// Semakin dekat tepi dengan sumbu minor, semakin datar dan lebih tipis elips, dan bahkan gangguan disebabkan. Ini adalah hasil skala.
// Kerugian ini terkadang merupakan keuntungan, seperti saat mengekspresikan efek tiga dimensi cincin (halo planet)
// Untuk kasus di mana parameter A atau B adalah 0, metode ini tidak berlaku
fungsi evencompellipse (konteks, x, y, a, b)
{
Context.Save ();
// Pilih yang lebih besar dari A dan B sebagai parameter radius dari metode busur
var r = (a> b)? A: B;
var rasiox = a / r; // rasio penskalaan sumbu horizontal
var ratioy = b / r; // rasio penskalaan sumbu dimensi
Context.Scale (rasiox, ratioy); // penskalaan (bahkan kompresi)
context.beginpath ();
// Gambar berlawanan arah jarum jam dari ujung kiri elips
context.moveto ((x + a) / rasiox, y / ratioy);
context.arc (x / rasiox, y / ratioy, r, 0, 2 * math.pi);
context.closepath ();
Context.stroke ();
Context.Restore ();
};
Metode kurva bezier kubik satuGambar kurva bezier kubik dari elips adalah perkiraan ketika benar -benar menggambar, dan secara teori itu juga merupakan perkiraan. Namun, karena efisiensinya yang tinggi, sering digunakan untuk menggambar elips dalam grafik vektor komputer, tetapi saya tidak terlalu jelas tentang teori spesifik. Perkiraan terletak pada pemilihan posisi dua titik kontrol. Posisi titik kontrol dari metode ini diperoleh sendiri dan akurasinya OK.
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Metode ini juga akan menghasilkan ketika linewidth lebih lebar dan elips lebih datar.
// ujung sumbu panjang tajam dan tidak halus
fungsi bezierellipse1 (konteks, x, y, a, b)
{
// Kuncinya adalah pengaturan dua titik kontrol di BezierCurveto
//0.5 dan 0,6 adalah dua koefisien utama (diperoleh untuk eksperimen dalam fungsi ini)
var ox = 0,5 * a,
oy = 0,6 * b;
Context.Save ();
context.translate (x, y);
context.beginpath ();
// Gambar berlawanan arah jarum jam dari ujung bawah sumbu longitudinal elips
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.closepath ();
Context.stroke ();
Context.Restore ();
};
Metode Kurva Bezier Kubik DuaMetode ini diubah dari balasan ke pos di stackoverflow, dengan akurasi tinggi dan juga merupakan metode yang biasa digunakan untuk menggambar elips.
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Metode ini juga akan menghasilkan ketika linewidth lebih lebar dan elips menyanjung
//, ujung sumbu panjang tajam dan tidak halus
// Metode ini lebih akurat dari metode Bessel sebelumnya, tetapi memiliki metode yang sedikit kurang efisien
fungsi bezierellipse2 (ctx, x, y, a, b)
{
var k = .5522848,
OX = A * K, // Offset Titik Kontrol Horizontal
oy = b * k; // Offset titik kontrol vertikal
ctx.beginpath ();
// Gambar empat kurva bezier kubik searah jarum jam dari titik ujung kiri elips
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.closepath ();
ctx.stroke ();
};
Metode kisiMetode ini dapat menggambar elips berdasarkan karakteristik kanvas yang dapat mengoperasikan piksel dan menggunakan algoritma dasar dalam grafik. Misalnya, algoritma elips menggambar titik tengah, dll.
Salah satu contohnya adalah posting blog oleh Doudou, teman taman, kelas perbaikan kanvas HTML5 (I) - Raster Graphics (1) Algoritma titik tengah dan lingkaran. Metode ini relatif primitif, fleksibel, efisien dan akurat, tetapi lebih rumit untuk mewujudkan fungsi yang berguna untuk menggambar elips. Misalnya, ketika lebar garis berubah, algoritma menjadi lebih rumit. Meskipun ini adalah algoritma untuk lingkaran menggambar, algoritma untuk menggambar elips mirip dengan itu, sehingga Anda dapat merujuknya di bawah ini.
Demo
Berikut ini adalah beberapa demonstrasi menggambar fungsi elips di samping metode raster. Kode demonstrasi adalah sebagai berikut:
<Div id = "canvaswrap" style = "latar belakang: #ffff; lebar: 600px; tinggi: 600px; Border: 1px solid black;"> </div>
<type skrip = "Text/JavaScript"> // <! [CDATA [
Var Canvas,
konteks;
var div = document.getElementById ("canvaswrap");
div.innerhtml = "";
canvas = document.createElement ("Canvas");
canvas.style.width = "600px"
canvas.style.height = "600px"
Canvas.width = 600;
Canvas.height = 600;
konteks = canvas.getContext ("2d");
Div.AppendChild (Canvas);
fungsi execdraw ()
{
// Selesaikan masalah lebar garis kurang dari atau sama dengan 1 di chrome
context.linewidth = 1.1;
Context.strokestyle = "Hitam"
Paramellipse (konteks, 130, 80, 50, 50); //Lingkaran
Paramellipse (konteks, 130, 80, 100, 20); // Ellipes
Evencompellipse (konteks, 130, 200, 50, 50); //Lingkaran
Evencompellipse (konteks, 130, 200, 100, 20); // Ellipe
Bezierellipse1 (konteks, 470, 80, 50, 50); //Lingkaran
Bezierellipse1 (konteks, 470, 80, 100, 20); // Ellipe
Bezierellipse2 (konteks, 470, 200, 50, 50); //Lingkaran
Bezierellipse2 (konteks, 470, 200, 100, 20); // Ellipe
// Deteksi kesamaan (derajat tumpang tindih)
Paramellipse (konteks, 300, 450, 250, 50);
context.strokestyle = "kuning";
Bezierellipse1 (konteks, 300, 450, 250, 50);
context.strokestyle = "biru";
Bezierellipse2 (konteks, 300, 450, 250, 50);
};
fungsi clearcavnas ()
{
Context.ClearRect (0, 0, 600, 600);
};
//]]> </script>
<p>
<tombol onclick = "execdraw ();" type = "Tombol"> Execute </button>
<tombol OnClick = "clearcanvas ();" type = "Tombol"> Bersihkan </button>
</p>
Perhatikan bahwa untuk menjalankan kode dengan sukses, diperlukan browser yang mendukung kanvas yang mendukung HTML5.
Itu adalah pertama kalinya saya menulis blog, dan tidak mudah untuk melakukannya sepanjang hari! Template kulit gelap di taman blog tidak menunjukkan kode yang dimasukkan dengan baik. Saya telah bersusah payah untuk mendapatkan format kode!