Saat saya browsing CSSDesignAwards, saya menemukan efek yang membagi konten gambar (website: https://weareludwig.com). dan efeknya cukup bagus. Periksa efeknya https://codepen.io/geeknoble/pen/OQaOVG
menganalisaPertama, kita dapat menemukan bahwa isi gambar dibagi menjadi beberapa persegi panjang kecil, dan setiap persegi panjang diterjemahkan secara acak. Fungsi drawImage pada Canvas dapat memotong konten gambar dan menariknya ke dalam kanvas Canvas, jadi prinsip implementasi utama dari efek ini adalah dengan menggunakan drawImage. Ada dua efek utama, yang pertama mengganggu dan memulihkan konten gambar, dan yang lainnya adalah beralih ke gambar berikutnya. DrawImage dapat digunakan untuk kedua efek tersebut, tetapi jarak pergerakannya berbeda. Setelah Anda memiliki gambaran umum, Anda dapat mulai menerapkannya.
pekerjaan awalPertama kita perlu menginisialisasi beberapa variabel, seperti lebar dan tinggi gambar, jumlah persegi panjang, ukuran pemotongan, dll., kemudian menghitung koordinat setiap persegi panjang, dan menggunakan loop ganda untuk menyimpan koordinat persegi panjang dalam data . Setiap persegi panjang mempunyai perpindahan acak. Diantaranya, x dan y mewakili koordinat kanvas kanvas, dan x1 dan y1 mewakili koordinat pemotongan gambar.
init: fungsi (konteks, lebar, tinggi, luas, img) { this.context = konteks; this.img = img; this.imgWidth = img[0].width; //Lebar dan tinggi gambar this.imgHeight = img[ 0 ].height; this.index = 0; //Nomor gambar saat ini this.width = lebar; //Lebar dan tinggi kanvas this.height = tinggi; //Panjang persegi panjang kecil this.countX = lebar / this.area; //Jumlah persegi panjang kecil pada arah horizontal dan vertikal this.countY = tinggi / this.area this.wx = this.imgWidth / this .countX; //Lebar dan tinggi gambar pada persegi panjang kecil this.wy = this.imgHeight / this.countY; this.state = true //Status gambar, true berarti tidak dipisahkan this.dataFlag = true; keadaan koordinat, benar berarti Tidak ada nilai acak durasi ini yang ditambahkan = 1000; //Waktu animasi this.duration2 = 1500; this.startTime = 0; this.data = []; //Informasi koordinat persegi panjang this.randoms = []; x1 = 0, y1 = 0, x = 0, y = 0; untuk (var i = 0; saya < ini.hitunganY; i++) { untuk (var j = 0; j < this.countX; j++) { konteks.drawImage(this.img[ini.index], x1, y1, this.wx, this.wy, x, y, this.area, this.area); ini.data.push({ x1: x1, y1: y1, x: x, y: y }); //Tambahkan nilai acak this.randoms.push(random(-this.area, this.area)); wy; x = 0; y += ini.area } ini.checkMargin();Deteksi tepinya
Sebelum menambahkan perpindahan pada persegi panjang, kita perlu menentukan apakah koordinat yang dipindahkan melebihi batas gambar. Misalnya, jika persegi panjang di atas bergerak pada sumbu y, maka syarat penilaiannya adalah apakah koordinat arus ditambah nilai perpindahannya kurang dari 0 atau Lebih besar dari lebar dan tinggi bayangan. Jika koordinat yang diperbarui kurang dari 0, maka nilai acak harus berupa angka negatif. Anda perlu mengubah nilai acak menjadi angka positif. Karena setiap persegi panjang bergerak dalam satu arah, saya tulis di sini bahwa bit bernomor genap menggerakkan sumbu x dan bit bernomor ganjil menggerakkan sumbu y.
//Deteksi tepi checkMargin: function () { var self = this.data.forEach(function (item, indeks) { if (index % 2 == 0) { // Pindahkan sumbu x ketika indeksnya adalah a kelipatan 2 , jika tidak, pindahkan sumbu y if (item.x1 + self.randoms[index] < 0) // Ubah ke bilangan positif self.randoms[index] = -self.randoms[index]; .x1 + self.wx + self.randoms[index] > self.imgWidth ) // Ubah ke angka negatif self.randoms[index] = -Math.abs(self.randoms[index]) } else { if (item.y1 + self .randoms[index] < 0) self.randoms[index] = -self.randoms[index]; jika (item.y1 + self.randoms[index] + self.wy > self.imgHeight) self.randoms[index] = -Math.abs(self.randoms[index]) } }) }pemisahan dan pemulihan
Pemisahan dan restorasi konten animasi adalah dengan memperbarui nilai koordinat persegi panjang. Untuk mengganggu konten, cukup tambahkan nilai acak pada koordinat dalam data, dan restorasi adalah dengan mengurangi nilai acak.
//Deteksi tepi checkMargin: function () { var self = this.data.forEach(function (item, indeks) { if (index % 2 == 0) { // Pindahkan sumbu x ketika indeksnya adalah a kelipatan 2 , jika tidak, pindahkan sumbu y if (item.x1 + self.randoms[index] < 0) // Ubah ke bilangan positif self.randoms[index] = -self.randoms[index]; .x1 + self.wx + self.randoms[index] > self.imgWidth ) // Ubah ke angka negatif self.randoms[index] = -Math.abs(self.randoms[index]) } else { if (item.y1 + self .randoms[index] < 0) self.randoms[index] = -self.randoms[index]; jika (item.y1 + self.randoms[index] + self.wy > self.imgHeight) self.randoms[index] = -Math.abs(self.randoms[index]) } }) }
Setelah menyimpan koordinat, Anda dapat mengimplementasikan animasi terjemahan. Proses pergerakan memiliki transisi yang mulus. Kita dapat menggunakan algoritma easing Tween.js. Algoritma ini memiliki 4 parameter: waktu saat ini, posisi awal, dan posisi akhir. waktu animasi. Untuk detailnya, silakan merujuk ke artikel Zhang Xinxu https://www.zhangxinxu.com/wordpress/2016/12/how-use-tween-js-animation-easing/. Tween.js dapat digunakan untuk menghitung jarak pergerakan di setiap frame, lalu menggunakan requestAnimationFrame untuk memperbarui koordinat.
blockAnimation: function () { var flag = 1; if (this.state) { // Tentukan apakah akan mengganggu gambar atau memulihkan gambar this.update(true) } else { flag = -1; ; } var self = ini; this.startTime = +new Date(); // Dapatkan waktu saat ini this.state = !this.state; >= self.startTime + self.duration) { // Kondisi akhir animasi kembali salah; easeInOut(t - self.startTime, 0, self.randoms[index] * flag, self.duration); Hitung jarak yang dipindahkan di setiap frame self.context.drawImage(self.img[self.index], item.x1 + pos, item.y1, self.wx, self.wy, item.x, item.y, self. area, self.area); } else { var pos = Math.tween.Expo.easeInOut(t - self.startTime, 0, self.randoms[index] * flag, self.duration); self.context.drawImage(self.img[self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area); } }); permintaanAnimationFrame(animasi);
Pada titik ini, animasi pemisahan dan restorasi telah dilaksanakan.
Peralihan gambarSelanjutnya, kita mulai memproses bagian peralihan gambar. Ini mirip dengan gambar carousel. Animasi gambar carousel memindahkan posisi setiap gambar berdasarkan lebar jendela visual ketinggian yang ingin dicapai y Mengaktifkan sumbu. Berbeda dengan gambar carousel, di sini kita hanya memiliki satu tag kanvas. Saat berpindah, kita hanya perlu mengubah koordinat gambar saat ini dan gambar berikutnya. Jarak pergerakan gambar saat ini adalah y1 + pos, dan jarak pergerakannya adalah gambar berikutnya adalah y1 + pos. - imgHeight (tentu saja mengapa imgHeight harus dikurangi).
//Animasi geser vertikal verticalAnimation: function (val) { if (!this.time2) { return false; } this.checkTime(2); Geser ke atas atau ke bawah if ((this.index + val) < 0 || (this.index + val) >= (this.img.length)) { // Tentukan apakah nomor seri gambar adalah hasil akhir yang salah } ini.negara bagian ? this.update(true) : this.update(false); this.startTime = +new Date(); (fungsi animasi() { var t = +new Date(); if (t >= self.startTime + self .duration2) { val === 1 ? self.index++ : self.img.length - 1 : self.index; .indeks >= self.img.length ? self.index = 0 : self.index; return false; } self.data.forEach(fungsi (item) { var pos = Math.tween.Cubic.easeInOut(t - self.startTime, 0, (self.imgHeight) * val, self.duration2); // Perbarui koordinat gambar saat ini self.context.drawImage(self.img[self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area); // Perbarui koordinat gambar berikutnya self.context.drawImage(self.img[ self.index + val], item.x1, item.y1 + pos - self.imgHeight * val, self.wx, self.wy, item.x, item.y, self.area, self.area); }); permintaanAnimationFrame(animasi);
Hal yang sama berlaku untuk perpindahan sumbu x. Sekarang semua fungsi hampir selesai. Kode lengkap dapat dilihat di codepen.
Di atas adalah keseluruhan isi artikel ini, saya harap dapat bermanfaat untuk pembelajaran semua orang. Saya juga berharap semua orang mendukung VeVb Wulin Network.