Kali ini saya akan membagikan cara menghaluskan tepi dan sudut segmen polyline yang digambar di kanvas, yaitu mengganti grafik polyline asli dengan melewatkan kurva Bezier melalui setiap titik gambar.
Mengapa segmen polyline pas dengan mulusPertama mari kita lihat efek rendering diagram garis di bawah Echarts:
Pada awalnya saya tidak menyadari bahwa segmen polyline ini sebenarnya adalah sebuah kurva yang melewatinya. Saya hanya mengira itu adalah gambar titik sederhana, jadi versi sederhana (jelek) dan mudah (jelek) yang saya terapkan pada awalnya adalah seperti ini:
Jangan memperhatikan gayanya, kuncinya adalah setelah implementasi, saya menemukan bahwa implementasi Echarts tampaknya sangat lancar, yang juga memicu diskusi selanjutnya. Bagaimana cara menggambar kurva halus secara teratur?
rendering
Mari kita lihat dulu penerapan tiruan terakhirnya:
Karena saya tidak tahu bagaimana Echarts diimplementasikan secara internal (escape
Itu sudah terlihat sangat bulat, sangat dekat dengan visi awal kita. Mari kita lihat apakah kurva melewati titik gambar:
OKE! Hasilnya jelas. Sekarang mari kita lihat penerapannya.
Proses implementasi
data simulasi
var data = [Math.random() * 300]; for (var i = 1; i < 50; i++) { //Ikuti grafik data.push(Math.round((Math.random() - 0.5) * 20 + data[i - 1])); } opsi = { kanvas:{ id: 'kanvas' }, seri: { nama: 'Data simulasi', gaya item: { warna: 'rgb(255, 70, 131)' }, gaya area: { warna: 'rgb(255, 158, 68)' }, data: data } };Gambarlah diagram garis
Pertama inisialisasi konstruktor untuk menempatkan data yang Anda perlukan:
function LinearGradient(option) { this.canvas = document.getElementById(option.canvas.id) this.ctx = this.canvas.getContext('2d') this.width = this.canvas.width this.height = this.canvas .height this.tooltip = option.tooltip this.title = option.text this.series = option.series //Penyimpanan data simulasi}Gambarlah diagram garis:
LinearGradient.prototype.draw1 = function() { //Garis referensi poliline... //Harus dianggap bahwa asal kanvas adalah pojok kiri atas, //Jadi beberapa konversi perlu dilakukan di bawah, //diff adalah x, sumbu y adalah data Bagian yang sama dari rentang nilai maksimum dan minimum. this.series.data.forEach(fungsi(item, indeks) { var x = diffX * indeks, y = Math.floor(self.height - diffY * (item - dataMin)) self.ctx.lineTo(x, y) //Plot titik data individual}) ...} Kurva Bezier pas mulusPoin kunci dari kurva Bezier adalah pemilihan titik kontrol. Situs web ini dapat secara dinamis menampilkan kurva berbeda yang digambar dengan titik kontrol berbeda. Dan untuk perhitungan titik kendali. . Penulis tetap memilih Baidu, lagipula dia kurang pandai matematika :). Siswa yang tertarik dengan algoritma tertentu dapat mempelajarinya lebih lanjut. Sekarang mari kita bicara tentang kesimpulan penghitungan titik kontrol.
Rumus di atas melibatkan empat titik koordinat, yaitu titik saat ini, titik sebelumnya, dan dua titik berikutnya. Bila nilai koordinatnya seperti pada gambar di bawah, maka kurva yang digambarkan adalah sebagai berikut:
Namun terdapat kendala rumus ini tidak dapat digunakan untuk titik awal dan titik terakhir, namun artikel tersebut juga memberikan metode untuk mengolah nilai batas:
Jadi ketika mengubah polyline menjadi kurva halus, hitung nilai batas dan titik kontrol lainnya dan substitusikan ke dalam fungsi Bessel:
//Implementasi inti this.series.data.forEach(function(item, index) { //Temukan titik kontrol antara titik sebelumnya dan titik berikutnya var scale = 0.1 //Untuk bilangan positif dari titik kontrol ab, Anda dapat Sesuaikan var last1X = diffX * (index - 1), last1Y = Math.floor(self.height - diffY * (self.series.data[index - 1] - dataMin)), //Koordinat titik sebelumnya last2X = diffX * (index - 2), last2Y = Math.floor(self.height - diffY * (self.series.data[index - 2] - dataMin)), //Dua titik pertama koordinat sekarangX = diffX * (index) , nowY = Math.floor(self.height - diffY * (self.series.data[index] - dataMin)), //Koordinat titik saat ini nextX = diffX * (index + 1), nextY = Math.floor(self.height - diffY * (self.series.data[index + 1] - dataMin)), //Koordinat titik berikutnya cAx = last1X + (nowX - last2X) * skala, cAy = last1Y + (nowY - last2Y) * skala, cBx = sekarangX - (nextX - last1X) * skala, cBy = sekarangY - (nextY - last1Y) * skala if(index === 0) { self.ctx.lineTo(nowX, nowY) return } else if(index ===1) { cAx = last1X + (nowX - 0) * skala cAy = last1Y + (nowY - self.height) * skala } else if (indeks === self.series.data.length - 1) { cBx = sekarangX - (sekarangX - 1X terakhir) * skala cBy = sekarangY - (sekarangY - 1Y terakhir) * skala } self.ctx.bezierCurveTo(cAx, cAy, cBx, cBy, nowX, nowY); //Gambarkan kurva Bezier dari titik sebelumnya ke titik saat ini})Karena titik yang saya lewati setiap kali adalah titik saat ini, tetapi rumus yang diberikan dalam artikel adalah algoritma titik kontrol yang menghitung titik berikutnya, maka dalam implementasi kode, saya memindahkan perhitungan semua titik satu tempat ke depan. Bila indeks = 0 yang merupakan titik awal, maka tidak perlu ditarik kurva, karena kita menggambar kurva dari titik sebelumnya ke titik saat ini, dan tidak ada kurva ke 0 yang perlu ditarik. Mulai dari indeks = 1, kita dapat mulai menggambar kurva secara normal dari 0 hingga 1, karena tidak ada titik kedua di depannya ketika indeks = 1, itu adalah titik nilai batas yang memerlukan perhitungan khusus, dan terakhir Sebuah titik . Selebihnya, hitung saja koordinat xy AB sesuai rumus normal dan substitusikan ke dalam fungsi Bessel.
akhirnyaLihat kode sumber di sini
Di atas adalah keseluruhan isi artikel ini, saya harap dapat bermanfaat untuk pembelajaran semua orang. Saya juga berharap semua orang mendukung VeVb Wulin Network.