Baru-baru ini, penulis memiliki persyaratan. Konten persyaratannya adalah: sekelompok teks ditampilkan di sekitar ring. Pengguna dapat menambahkan teks. Teks yang mengelilingi ring. Setiap kata sesuai dengan titik biru kecil di sekitar ring arahkan mouse ke Titik biru kecil di atas cincin akan memancarkan segitiga dan kemudian menampilkan teksnya. Mari kita lihat efek animasinya terlebih dahulu!
Seperti yang ditunjukkan pada gambar di atas, ketika mouse diletakkan pada titik biru kecil yang sesuai, sinar seperti segitiga perlu dipancarkan, dan teks yang sesuai ditampilkan di luar segitiga, dan titik biru kecil menjadi titik putih kecil.
Saat pengguna memasukkan konten di atas, konten tersebut ditambahkan di sekitar ring di bawah. Seperti terlihat pada gambar di atas.
Ide awal penulis adalah menggunakan css untuk mengimplementasikannya, seperti menu sekunder dinamis pada gambar di bawah.
Namun, mengingat konten di tepi ring bervariasi dan perlu diposisikan di sekitar ring, CSS mungkin sulit untuk diterapkan. Wah, penulis memutuskan untuk menggunakan kanvas untuk mencapainya. (Penulis baru mempelajari Canvas. Jika ada yang salah saya terima koreksinya).
Proses implementasi:Pertama:
Bagian html dari kodenya adalah sebagai berikut:
<canvas style=margin-left: 50px;padding-top: 20px; display:block; id=canvas > Versi browser Anda saat ini tidak mendukung kanvas</canvas>
Langkah-langkah implementasi spesifiknya adalah sebagai berikut:
1. Gambarlah sebuah lingkaran besar.
Gunakan metode kanvas: konteks.arc(x, y, radius, startAngle, endAngle [, berlawanan arah jarum jam]);
x, y: koordinat pusat lingkaran, radius: radius pusat lingkaran, startAngle: menggambar radian awal, endAngle: menggambar radian akhir, [, berlawanan arah jarum jam]: parameter opsional, apakah akan menggambar busur searah jarum jam atau berlawanan arah jarum jam.
Untuk kemudahan menggambar, penulis memindahkan asal kanvas dari sebelumnya pojok kiri atas ke tengah kanvas.
Jari-jari cincin yang dihitung penulis adalah r-80
canvas.width = 500canvas.height = 500//Hitung jari-jari pusat kanvas misalkan r = 500 / 2//Pindahkan asal kanvas ke tengah kanvas saat antarmuka diinisialisasi ctx.translate(r ,r) //Pindahkan kuas ke bulat
Kode spesifiknya adalah sebagai berikut:
//Inisialisasi kanvas biarkan kanvas = document.getElementById('canvas')let ctx= canvas.getContext('2d')let rasio = getPixelRato(ctx)canvas.width = 500canvas.height = 500//Hitung radius pusatnya dari kanvas misalkan r = 500 / 2// Saat antarmuka diinisialisasi, pindahkan asal kanvas ke tengah kanvas ctx.translate(r,r) //Pindahkan kuas ke lingkaran ctx.lineWidth = 3; //Atur lebar garis kuas ctx.beginPath(); //Mulai kuas//Gambarlah warna tepi gradien dari tepi lingkaran var arcColor = ctx.createLinearGradient(-170, -170, 0, 170)arcColor.addColorStop(0, '#8ec1ff')arcColor.addColorStop(0.2, '#83beff')arcColor.addColorStop(0.5, '#75b1ff')arcColor.addColorStop(0.7,'#5998ff')arcColor.addColorStop(1, '#2065ff')ctx .strokeStyle= arcColor;//Mengatur warna kuas ctx.arc(0,0,r - 80,0,2*Math.PI,false) //Menggambar sebuah lingkaran, koordinat 0,0, radius 250-80, lingkaran penuh (0 -360 derajat), false berarti searah jarum jam ctx.closePath()ctx.stroke() //MenggambarHasil gambarnya adalah sebagai berikut
2. Gambarlah gambar background di tengah ring (asal kanvas saat ini adalah bagian tengah kanvas)
drawImage(gambar, dx, dy, dLebar, dTinggi)
gambar: Sumber daya gambar kanvas, seperti gambar <img>, gambar SVG, elemen Canvas itu sendiri, dll.
dx, dy: Merencanakan suatu area pada kanvas Canvas untuk menempatkan gambar. dx adalah koordinat horizontal dan vertikal dari sudut kiri atas area tersebut.
dLebar, dTinggi: Rencanakan area pada kanvas Kanvas untuk menempatkan gambar, lebar dan tinggi area tersebut.
Berikut koordinat yang dihitung oleh penulis
let image = new Image()image.src = 'image/quan.png'image.onload = () => { // Pindahkan titik asal ke tengah ctx.drawImage(image,-140,-140,280,280)}Hasil gambarnya adalah sebagai berikut:
3. Gambarlah teks dan titik-titik kecil pada ring (asal kanvas saat ini adalah bagian tengah kanvas)
Menggambar target untuk teks dan titik-titik kecil:
3.1 Titik-titik kecil ditampilkan secara merata pada cincin besar
3.2 Teks tersebar sedikit di luar titik-titik kecil
Larutan:1. Penulis menggunakan array untuk menyimpan kata-kata saat ini
let textArr = ['Laut dan langit yang luas','Kemampuan teknis','Dana yang kuat','Kontrol pemeliharaan','Hidup dan bekerja dalam damai dan kepuasan','Perhatikan bunganya','Selesaikan sentuhan akhir',' Singkirkan sampah',' Melawan angin',' pengembangan karier']
2. Karena jumlah titik kecil dan jumlah kata sama, maka jumlah keduanya adalah panjang array textArr di atas.
3. Radian suatu lingkaran penuh adalah 2π. Untuk membuat titik-titik kecil membagi cincin secara merata, penulis menghitung terlebih dahulu radian titik di mana setiap titik kecil berada.
for(let i = 0;i<lengths;i++){ // Hitung radian let rad = 2*Math.PI/lengths*i}4. Berdasarkan fungsi trigonometri, koordinat (x, y) titik kecil saat ini pada kanvas dapat dihitung (asal usul kanvas saat ini adalah pusat kanvas)
Diantaranya hubungan antara radian, titik kecil, cincin, jari-jari cincin dan asal kanvas, penulis membuat gambar untuk mendeskripsikannya.
Hitung koordinat teks:
// Hitung koordinat pusat lingkaran kecil misalkan x = (r - 40)*Math.cos(rad)misalkan y = (r - 40)*Math.sin(rad)
Hitung koordinat titik kecil: Karena pusat titik kecil harus terletak di atas ring, maka koordinat horizontal dan vertikal yang dihitung adalah,
// Hitung koordinat teks misalkan x = (r - 80)*Math.cos(rad) misalkan y = (r - 80)*Math.sin(rad)
Kode spesifiknya adalah sebagai berikut:
// Menggambar teks ctx.font = '13px Arial'ctx.textAlign = 'center'ctx.textBaseline = 'middle'ctx.fillStyle=#000000let lengths = textArr.lengthtextArr.forEach(function(text,i){ //radian misalkan rad = 2*Math.PI/lengths*i // Hitung koordinat pusat lingkaran kecil misalkan x = (r - 40)*Math.cos(rad) let y = (r - 40)*Math.sin(rad) ctx.fillText(text,x+0.5,y+0.5)});// Gambar titik-titik kecil for(let i = 0;i<panjang;i++){ // // misalkan rad = 2*Math.PI/lengths*i misalkan x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)// // Gambar titik-titik kecil berwarna abu-abu tembus pandang di tepinya ctx.beginPath() ctx.fillStyle = 'rgba(226,235,250, 0,8)' ctx.arc(x,y,8,0,2*Matematika.PI,salah) ctx.closePath() ctx.fill() // Menggambar titik biru kecil ctx.beginPath() ctx.fillStyle = '#208fe5' ctx.arc(x,y,4,0,2*Math.PI,false) ctx.closePath( ) ctx .mengisi() }Hasil gambarnya adalah sebagai berikut:
4. Gambarlah sebuah segitiga di luar setiap titik kecil (asal usul kanvas saat ini adalah bagian tengah kanvas)
4.1 Karena ingin menggambar bentuk segitiga, maka ide menggambar segitiga adalah menggambar garis pada kedua sisinya dengan titik tengah titik kecil saat ini sebagai titik awal, kemudian gunakan ctx.fill() untuk menutup bentuk dan isi interior dengan warna gradien.
Gambarlah sebuah segitiga: koordinatnya dihitung sendiri. Penulis tambah dan kurangi 35 pada sumbu absis dan 70 pada ordinatnya (terserah saja, hahaha)
//Mulai kuas ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath()
Gambarlah teks di bawah segitiga: (Untuk membedakannya dari teks sebelumnya, saya menggunakan warna merah untuk teks saya di sini)
ctx.fillStyle= '#e3211c' ctx.fillText(teksArr[i],x,y+75)
Kode spesifiknya adalah sebagai berikut:
for(misalkan i = 0;i<panjang;i++){ // // misalkan rad = 2*Math.PI/lengths*i misalkan x = (r - 80)*Math.cos(rad) misalkan y = (r - 80)*Math.sin(rad) // // Menggambar segitiga // // ctx.rotate( -Math.PI / 4) ctx.beginPath() //Mulai kuas ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath() // // Tetapkan gradien warna- - ->Tambahkan warna dari tengah ke kedua sisi var sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0,6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0,8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(teksArr[i],x,y+75)}Hasil gambarnya adalah sebagai berikut:
4.2 Syaratnya adalah arah setiap segitiga harus menyebar ke luar, dan sekarang arah segitiganya ke bawah, jadi sekarang Anda perlu menggunakan metode memutar kanvas.
ctx.save() ctx.translate(x,y) // Sudut rotasi berpusat pada setiap titik kecil ctx.rotate( rad - Math.PI/2 ) // Karena titik kecil ctx.translate(- x, - y) . Hilangkan kode untuk menggambar segitiga dan teks.
Terlihat dari perhitungan bahwa dengan mengambil titik tengah titik kecil sebagai titik awal putaran, maka busur putaran segitiga haruslah busur titik kecil saat ini dikurangi π/2, karena posisi awal putaran selalu dimulai dari arah positif sumbu koordinat x, yaitu dimulai dari 0 radian, namun sekarang segitiga-segitiga tersebut semuanya berada pada π/2 radian, jadi:
Radian rotasi = Radian titik kecil - π/2
Ingatlah untuk menggunakan metode penyimpanan status Canvas save() saat memutar.
memulihkan() memunculkan status Canvas yang disimpan dari atas tumpukan secara bergantian. Jika tidak ada status Canvas yang disimpan, tidak akan ada perubahan dalam menjalankan metode ini.
Pastikan untuk mengingat untuk menggunakan metode restore() di akhir. Pada titik ini, penulis menitikkan air mata penyesalan. . .
Kode khusus:
for(misalkan i = 0;i<panjang;i++){ // // misalkan rad = 2*Math.PI/lengths*i misalkan x = (r - 80)*Math.cos(rad) misalkan y = (r - 80)*Math.sin(rad) // Menggambar segitiga s ctx.save() // Sudut rotasi berpusat pada setiap titik kecil karena titik-titik kecil berada di awal ctx.translate(x,y) ctx.rotate( rad - Math.PI/2 ) ctx.translate(-x, -y) // Mulai kuas ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+ 70 ) ctx.lineTo(x+35,y+70) ctx.closePath() //Atur gradien warna--->Tambahkan var warna dari tengah ke kedua sisi sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0,7,'rgba(129,200,224,0.5)') sColor.addColorStop(0,8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75) ctx.restore()}Gambarkan hasilnya:
Coba lihat lebih dekat, apa? ? ? Beberapa teks terbalik karena masalah rotasi. Melalui pengamatan, hasilnya adalah ketika radian lebih besar dari π, teks menjadi terbalik.
Saatnya untuk menulis gelombang penilaian. . . .
Cara memutar teks:
function memutarContext(ctx, x, y, derajat) { // Memutar teks ctx.translate(x, y) // ctx.rotate(derajat * Math.PI / 180) ctx.rotate(derajat) ctx.translate(-x , -y) }Tentukan titik-titik kecil yang radiannya lebih besar dari π
if (rad > Math.PI) { // Karena teks perlu ditampilkan di tepi segitiga, teks harus diputar bersama segitiga agar selalu dipertahankan di // tepi segitiga setelah diputar , teks akan muncul ketika radian lebih besar dari π. Balikkan soal, jadi putar teks ctx.save() ctx.beginPath() // Putar teks memutarContext(ctx, x, y+75, Math.PI) ctx.font = '13px Arial' ctx.textAlign = 'tengah' ctx.fillStyle = #ff2238 ctx.fillText(textArr[i], x, y+ 75) ctx.restore()} else { ctx.fillStyle = '#ff2238' ctx.fillText(textArr[i ], x, kamu + 75)}Hasil gambarnya adalah sebagai berikut:
Menantikan kemenangan, kita hampir berhasil. Setidaknya kita memiliki tata letak yang kasar. Revolusi belum berhasil, dan kawan-kawan masih harus bekerja keras! !
5. Berikut implementasinya, ketika mouse berada di atas titik kecil, segitiga pada tepi dan teks pada tepi segitiga akan ditampilkan, namun teks pada tepi lingkaran tidak ditampilkan.
Ide:1. Ikat acara entri mouse ke kanvas
2. Tentukan apakah koordinat posisi mouse saat ini di kanvas sama dengan koordinat di dekat titik kecil. Jika ya, tampilkan segitiga yang sesuai dengan titik kecil tersebut.
5.1 Ikat acara mousemove ke kanvas: mouse berada di atas acara tersebut
kanvas.addEventListener('mousemove',clickEvent)5.2 Hitung koordinat mouse saat ini di kanvas
Cara perhitungannya adalah: gunakan koordinat mouse saat ini di DOM untuk mengurangi jarak dari kiri atau atas kanvas untuk menghitung jarak kanvas.
Metode drawOne pada gambar di bawah ini merupakan metode menggambar yang akan dibahas nanti pada artikel.
function clickEvent() { // Koordinat posisi mouse let x = event.clientX - canvas.getBoundingClientRect().left let y = event.clientY - canvas.getBoundingClientRect().top drawOne(x,y)}5.3, karena koordinat mouse pada kanvas yang dihitung di atas dihitung dengan sudut kiri atas kanvas sebagai asal, tetapi asal kanvas saat ini sudah berpindah ke tengah kanvas (250.250), jadi ketika digunakan untuk menentukan apakah suatu klik berupa titik-titik kecil Anda perlu mengurangi 250 dari koordinat horizontal dan vertikal untuk membandingkannya dengan koordinat titik kecil di kanvas saat ini. Saat saya membuat penilaian, saya menemukan masalah dari penulis adalah 260 bukannya 250. Jadi penulis mengurangi 260 ke arah y.
Kodenya adalah sebagai berikut:
Diantaranya, Cx, Cy adalah koordinat mouse pada kanvas (pojok kiri atas kanvas adalah titik asal), x, y adalah koordinat titik kecil saat ini,
Penulis langsung menghitung posisi 15px di dekat pusat titik kecil, dan semua segitiga ditampilkan, dan titik kecil menjadi putih.
Yang paling penting adalah Anda harus menghapus kanvas sebelumnya setiap kali Anda menggambar ulang: ingatlah untuk menggunakan metode clearRect untuk menghapus kanvas
misalkan XX = Cx - 250biarkan YY = Cy- 260biarkan kiriX = x - 15 biarkan kananX = x + 15biarkan atasY = y - 15biarkan bawahY = y + 15if (XX >= kiriX && XX <= kananX && YY <= bawahY && YY > = topY ) {//Diklik. . . . . . //Tuliskan kode gambar di tengah}Kode ini diikuti oleh tautan:
6. Tentukan Input pada antarmuka dan ikat peristiwa perubahan ke input.
Implementasi: Antarmuka digambar ulang setiap kali nilai dalam Input berubah.
kode html:
<input type=text id=inpt style=margin-left: 100px;margin-top: 50px placeholder=Silahkan masukkan...>
kode js:
biarkan inpt = document.getElementById('inpt') inpt.addEventListener('change', function () { if (inpt.value !== '') { textArr.push(inpt.value) drawAll(2) //Ini Caranya adalah dengan cara menggambar, source codenya akan diberikan nanti di artikel}})7. Ada masalah. Setiap kali Anda mengklik antarmuka dan menggambar ulang antarmuka, akan ada situasi berkedip.
Seperti yang ditunjukkan di bawah ini:
Setiap kali Anda menggeser, karena koordinat mouse berubah, Anda perlu menghapus konten di sekitar ring dan menggambar ulang. Jadi, Anda perlu membersihkan kanvas untuk mendapatkan efek dinamis.
clearRect() sangat umum digunakan dalam gambar animasi Canvas. Ini terus-menerus membersihkan konten kanvas dan kemudian menggambarnya untuk membentuk efek animasi.
clearRect() dapat membuat area persegi panjang di kanvas elemen Canvas menjadi transparan.
konteks.clearRect(x, y, lebar, tinggi);
x, y: x, y koordinat sudut kiri atas persegi panjang.
width, height: lebar dan tinggi area persegi panjang yang dibersihkan.
Karena clearRect() hanya dapat menghapus area persegi panjang pada kanvas, setiap kali dibersihkan, gambar latar belakang di tengah akan dihapus secara bersamaan.
Oleh karena itu, gambar latar belakang harus dimuat ulang setiap saat, dan diperlukan waktu tertentu untuk memuat gambar tersebut, sehingga akan berkedip setiap kali muncul.
Larutan:drawImage(gambar, dx, dy, dLebar, dTinggi)
Gambar parameter: Sumber daya gambar kanvas, seperti gambar <img>, gambar SVG, elemen Canvas itu sendiri, dll.
Kemudian Anda dapat menggunakan kanvas lain untuk menyimpan gambar dalam cache.
Gunakan kanvas tambahan untuk menggambar gambar latar belakang, tetapi untuk kanvas itu tidak ditampilkan di antarmuka: display:none, lalu gunakan untuk menghapus kanvas dan langsung merender objek kanvas yang di-cache ke tengah kanvas yang akan ditampilkan, itu adalah, tidak perlu memakan waktu lama untuk memuat gambar satu kali.
kode html:
<lebar kanvas=280 tinggi=280 style=margin-kiri: 50px;padding-atas: 20px; tampilan:tidak ada; id=kanvas2> </kanvas>
kode js:
//Gunakan caching untuk memecahkan masalah flashing gambar yang digambar ulang var tempCanvas = document.getElementById('canvas2')const tempCtx = tempCanvas.getContext('2d')tempCanvas.width = 280; )image.src = 'image/quan.png'image.onload = () => { // Asal berpindah ke tengah tempCtx.drawImage(image,0,0,280,280)}Setelah membersihkan kanvas, gambarkan canvas:tempCanvas yang di-cache secara langsung saat menggambar ulang gambar.
// Gambarkan kanvas yang di-cache langsung ke antarmuka (antarmuka ban perantara di-cache) ctx.drawImage(tempCanvas,-140,-140)
Oke saya berhasil, berikut gambar hasilnya :
Alamat kode sumbernya adalah sebagai berikut:
https://github.com/Linefate/Dynamic-effect-of-canvas-ring.git
MeringkaskanDi atas adalah perkenalan editor dalam menggunakan kanvas html5 untuk menggambar animasi cincin. Saya harap ini dapat membantu Anda. Jika Anda memiliki pertanyaan, silakan tinggalkan pesan kepada saya dan editor akan membalas Anda tepat waktu. Saya juga ingin mengucapkan terima kasih kepada semua orang atas dukungan Anda terhadap situs seni bela diri VeVb!