Tidak ada yang terbaik, yang ada hanya lebih baik. Sesuai dengan judulnya, artikel ini hanya ingin berbagi efek pergerakan partikel yang dicapai dengan menggunakan Canvas. Terasa seperti headline, tapi dari sudut pandang lain, hampir tidak bisa dianggap mempesona. Meski warnanya tidak ada hubungannya dengan mempesona, namun efek gerakannya tetap sedikit mempesona. Bagaimanapun, mari kita mulai apa yang disebut efek mempesona ini!
Langsung saja ke kodenya, jika kurang paham bisa baca komentar kodenya. Anda mungkin akan memahami gambaran umumnya.
kode html
<!DOCTYPE html><html lang=en><head><meta charset=UTF-8><title>Kanvas menghasilkan efek gerakan partikel yang mempesona - Front end perpustakaan Cloud</title><style>* { margin: 0; : 0;}html,tubuh { lebar: 100%; tinggi: 100%;}kanvas { tampilan: blok; latar belakang: #000;}tubuh::-webkit-scrollbar{ tampilan: tidak ada;}.operator-box{ posisi: tetap; atas: 0; kiri: 50%; batas: 1px solid #fff; latar belakang: rgba(255,255,255,0.5); (-50%); transformasi: terjemahanX(-50%);}.tipe-kembali,.hidup-kembali{ margin-kanan: 20px;}.flex-box{ tampilan: flex; justify-content: center; align-items: center;}#input-text{ tinggi baris: 35px; lebar: 260px tinggi: 35px; 0, 0,0.7); warna: #fff; ukuran font: 16 piksel; batas: tidak ada; garis besar: tidak ada; 12px; bayangan kotak: sisipkan 0 0 12px 1px rgba(0,0,0,0.7);}#input-text::placeholder{ warna: #ccc; tinggi garis: 55px tinggi: 55px;}pilih{ - penampilan webkit: tidak ada; -penampilan moz: tidak ada; penampilan: tidak ada; batas: tidak ada; 0px 6px; tinggi: 35px; warna: #fff; perataan teks: kiri; latar belakang: rgba(0, 0, 0,0.7) url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAx8TU7AAAAOUlEQ…R4gPgWEIMAiOYBCS4C8ZDAIrBq4gigNkztQEFMi6AuQHESAPMeXiEMiWfpAAAAAElFTkSuQmCC) tanpa pengulangan 190px 12px; ukuran latar belakang: 5px 8px; bayangan kotak: sisipan 0 0 12px 1px rgba(0,0,0,0.7);}</style></head><body><div class=operator-box>< div class=flex-box> <div class=back-type>Jenis spread: <select name= id=selectType> <option value=back>Kembali</option> <option value=auto>Acak</option> </select> </div> <div class=back-animate>Efek dispersi (efektif untuk homing): <select class=back-dynamics id=selectDynamics> <option value= spring>dynamics.spring</option> <option value=bounce>dynamics.bounce</option> <option value=forceWithGravity>dynamics.forceWithGravity</option> <option value=gravity>dynamics.gravity</option> <option value=easeInOut>dynamics.easeInOut</option> <option value=easeIn>dynamics.easeIn</option> <option value=easeOut>dynamics.easeOut</ option> <option value=linear>dynamics.linear</option> </select> </div> <div class=input-box><input type=text placeholder=Masukkan karakter Cina dan tekan Enter id=input-text></div></div></div><script src=dynamics.min.js></script><script src=index.js></ skrip ><skrip>var iCircle = Lingkaran baru();</script></body></html>
Tidak banyak kode HTML, hanya beberapa elemen operasi. Sekilas mudah dipahami di sini. Tidak perlu membuang terlalu banyak kata. Mari kita lihat kode JavaScript protagonis artikel ini. Namun, sebelum melihat kodenya, sebaiknya kita mendengarkan gagasan untuk mencapai efek ini:
Tiga Kanvas digunakan dalam kode JavaScript, this.iCanvas (halaman beranda), this.iCanvasCalculate (digunakan untuk menghitung lebar teks), dan this.iCanvasPixel (digunakan untuk menggambar teks dan mendapatkan koordinat posisi piksel yang sesuai dengan teks ) .
this.iCanvasCalculate dan this.iCanvasPixel tidak perlu ditampilkan di halaman, keduanya hanya fungsi tambahan.
Berikut adalah kode implementasi JS yang mengagumkan
function Circle() { var This = this; this.generalRandomParam(); this.drawCircles(); this.ballAnimate(); Dapatkan layar window.onresize = function(){ This.stateW = document.body.offsetWidth; This.stateH = document.body.offsetHeight; This.iCanvas.width = This.stateW; This.iCanvasH = This.iCanvas.height = This.stateH; This.ctx = This.iCanvas.getContext(2d); ){ //Lebar dan tinggi elemen induk this.stateW = document.body.offsetWidth; this.stateH = document.body.offsetHeight; document.createElement(canvas); // Atur Canvas agar memiliki lebar dan tinggi yang sama dengan elemen induk this.iCanvasW = this.iCanvas.width = this.stateW this.iCanvasH = this.iCanvas.height = this.stateH; // Dapatkan lukisan 2d Environment this.ctx = this.iCanvas.getContext(2d); // Masukkan ke dalam elemen body document.body.appendChild(this.iCanvas); this.iCanvasCalculate = document.createElement(canvas); // Kanvas digunakan untuk menyimpan lebar teks yang dihitung this.mCtx = this.iCanvasCalculate.getContext(2d); (kanvas); this.iCanvasPixel.setAttribute(style,position:absolute;top:0;left:0;); this.pCtx = null; // Kanvas yang digunakan untuk menggambar teks // Jumlah lingkaran yang dihasilkan secara acak this.ballNumber = ramdomNumber(1000 , 2000); // Simpan array semua bola this.balls = []; // Simpan bola terakhir yang berhenti bergerak di animasi this.animte = null; this.imageData = null; this.textWidth = 0; // Simpan lebar teks yang dihasilkan this.textHeight = 150; // Simpan tinggi teks yang dihasilkan this.inputText = ; this.actionCount = 0; this.ballActor = []; // Simpan partikel yang menghasilkan teks this.actorNumber = 0; // Simpan jumlah partikel yang menghasilkan teks this.backType = back; ; // Efek animasi this.isPlay = false; // Logo (tidak dapat dibuat selama pembuatan teks)}// Render semua lingkaran Circle.prototype.drawCircles = function () { for(var i=0;i <this.ballNumber ;i++){ this.renderBall(this.balls[0]); }}// Dapatkan teks masukan pengguna Circle.prototype.getUserText = function(){ This = this; // Simpan ini untuk menunjuk ke ipu = document.getElementById(input-text); ipu.addEventListener(keydown,function(event){ if(event.which === 13){ // Jika itu adalah tombol enter ipu.value = ipu.value.trim(); // Hapus spasi di awal dan akhir var pat = /[/u4e00-/u9fa5]/; // Penilaian bahasa Mandarin var isChinese = pat.test(ipu.value); if(ipu.value.length !=0 && isChinese){ This.inputText = ipu.value; }else{ alert(Silahkan masukkan karakter Cina return; ) { kembali } Ini.getAnimateType(); Ini.getTextPixel(); Ini.isPlay = benar; Hitung lebar teks Circle.prototype.calculateTextWidth = function () { this.textWidth = this.mCtx.measureText(this.inputText).width;}// Dapatkan piksel teks Circle.prototype.getTextPixel = function () { jika( ini.pCtx){ this.pCtx.clearRect(0,0,this.textWidth,this.textHeight); } this.calculateTextWidth(this.inputText); this.iCanvasPixel.width = this.textWidth; .pCtx = ini.iCanvasPixel.getContext(2d); this.pCtx.font = 128px Microsoft Yahei; this.pCtx.fillStyle = #FF0000; this.pCtx.textBaseline = bawah; this.pCtx.fillText(ini.inputText,0,110); 0,0,ini.Lebarteks,ini.Tinggiteks).data; this.getTextPixelPosition(this.textWidth,this.textHeight);}//Dapatkan posisi piksel partikel teks Circle.prototype.getTextPixelPosition = function (width,height) { var left = (this.iCanvasW - width)/2; = (ini.iCanvasH - tinggi)/2; var spasi = 4; this.actionCount = 0; i=0;i<this.textHeight;i+=spasi){ for(var j=0;j<this.textWidth;j+=spasi){ var indeks = j*spasi+i*this.textWidth*4; this.imageData[index] == 255){ if(this.actionCount<this.ballNumber){ this.balls[this.actionCount].status = 1; this.balls[this.actionCount].targetX = kiri+j; this.balls[this.actionCount].targetY = atas+i; this.balls[this.actionCount].backX = this.balls[this.actionCount]. x; ini.bola[ini.actionCount].backY = ini.bola[ini.actionCount].y; ini.ballActor.push(ini.bola[ini.actionCount]); } } } this.actorNumber = this.ballActor.length; } this.animateToText();}//Partikel berpindah ke posisi yang ditentukan Circle.prototype.animateToText = function(){ for(var i=0;i<Ini .actorNumber ;i++){ dinamika.animate(Ini.ballActor[i], { x: ini.ballActor[i].targetX, y: this.ballActor[i].targetY },{ ketik: dinamika.easeIn, durasi: 1024, } } setTimeout(function(){ This.ballbackType(); },3000);}//Partikel kembali ke Lingkari sepanjang jalur asli .prototype.ballBackPosition = function(){ for(var i=0;i<This.actorNumber;i++){ var ball = This.ballActor[i];dynamics.animate(ball, { x: ball.backX, y: ball.backY },{ ketik: dinamika[this.backDynamics], durasi: 991, selesai:this.changeStatus(ball) } }}// Dapatkan tipe|efek animasi Circle.prototype.getAnimateType = function() { var selectType = document.getElementById(selectType); var selectDynamics = document.getElementById(selectDynamics); this.backType = selectType.options[selectType.options.selectedIndex].value this.backDynamics = selectDynamics.options[selectDynamics.options.selectedIndex].value;}//Setel ulang Lingkaran penyebaran .prototype.ballbackType = function(){ if(this.backType == kembali){ this.ballBackPosition(); }else{ this.ballAutoPosition(); } this.ballActor = [];}// Menyebarkan secara acak Circle.prototype.ballAutoPosition = function(ball){ for(var i= 0 ;i<ini.actorNumber;i++){ ini.changeStatus(ini.ballActor[i]) }}// Mengubah status bola Circle.prototype.changeStatus = function(ball){ ball.status = 0; if(this.isPlay == true){ this.isPlay = false }}// Menghasilkan parameter yang relevan dari setiap lingkaran secara acak; .prototype.generalRandomParam = function(){ for(var i=0;i<this.ballNumber;i++){ var ball = {}; ball.size = 1; Menghasilkan radius lingkaran secara acak // Menghasilkan secara acak pusat lingkaran x koordinat ball.x = ramdomNumber(0+ball.size, this.iCanvasW-ball.size); .ukuran); bola.speedX = ramdomNumber(-1, 1); bola.speedY = ramdomNumber(-1, 1); ball.status = 0; ball.targetX = 0; ball.targetY = 0; ball.backX = 0; ball.backY = 0; for( var i=0;i<ini.bolaNumber;i++){ jika( ini.bola[i].status == 0){ ini.bola[i].x += this.balls[i].speedX; this.balls[i].y += this.balls[i].speedY; } }}// Menggambar lingkaran Circle.prototype.renderBall = function(ball){ this.ctx .fillStyle = #fff; this.ctx.beginPath(); // Ini harus ditambahkan dengan this.ctx.arc(ball.x, ball.y, ball.size, 0, 2 * Math.PI); this.ctx.closePath(); // Ini harus ditambahkan dengan this.ctx.fill();}// Penilaian tabrakan bola Circle.prototype.collision = function(ball){ for(var i= 0;i<ini.ballNumber;i++){ if(ball.x>ini.iCanvasW-ball.size || ball.x<ball.size){ if(bola.x>ini.iCanvasW-bola.ukuran){ bola.x = ini.iCanvasW-bola.ukuran; }else{ bola.x = bola.ukuran; } bola.kecepatanX = - bola.kecepatanX } jika (bola.y>ukuran bola-iCanvasH ini || bola.y<ukuran bola){ if(bola.y>ukuran bola-iCanvasH ini){ bola.y = this.iCanvasH-ball.size; }else{ ball.y = ball.size; } ball.speedY = - ball.speedY; } }}// Mulai animasi Circle.prototype.ballAnimate = function(){ var This = ini ; var animateFrame = jendela.requestAnimationFrame ||. jendela.mozRequestAnimationFrame || window.msRequestAnimationFrame; (fungsi pindah(){ animte = animateFrame(pindah); This.ctx.clearRect(0, 0, This.iCanvasW, This.iCanvasH); This.changeposition(); for(var i=0;i <Ini.bolaNumber;i++){ Ini.tabrakan(Ini.bola[i]); Ini.renderBall(Ini.bola[i] } })();}//Hasilkan fungsi bilangan acak ramdomNumber(min, max) { return Math.random() * (max - min) + min;}
Setelah membaca kodenya, saya kira itu hanya sedikit pamer, dan itu tidak membuat Anda ingin membuat hal ini. Untuk alasan ini, saya tahu Anda harus diyakinkan oleh mata Anda. DEMO Online: Contoh partikel dinamis.
Tidak ada seorang pun yang sempurna, begitu pula kode. Tampaknya kode yang berjalan dengan lancar juga memiliki beberapa kekurangan. Saat ini, efek ini hanya mendukung bahasa Mandarin. Kalau bahasa Inggris, saya harus bekerja lebih keras. Bagaimanapun, bahasa Inggris pasti akan bergabung nanti, itu hanya masalah waktu. Ada juga atribut dalam kode yang digunakan untuk menandai apakah teks yang dihasilkan dapat dieksekusi lagi: this.isPlay, yang masih memiliki sedikit kekurangan. Perubahan status this.isPlay tidak berubah tepat pada saat partikel kembali. tetapi mengubah keadaan terlebih dahulu. Namun keadaan ini tidak akan mempengaruhi implementasi penuh dari efek contoh ini.
Dalam contoh ini, perpustakaandynamic.js digunakan, terutama untuk menggunakan beberapa fungsi gerak di dalamnya untuk membuat partikel bergerak lebih mengesankan, itu saja.
Di atas adalah keseluruhan isi artikel ini, saya harap dapat bermanfaat untuk pembelajaran semua orang. Saya juga berharap semua orang mendukung VeVb Wulin Network.