Membuat Jam dengan Fungsi Trigonometri sin() dan cos() CSS Baru

Membuat Jam dengan Fungsi Trigonometri sin() dan cos() CSS Baru

Node Sumber: 1999799

Fungsi trigonometri CSS ada di sini! Ya, itu jika Anda menggunakan Firefox dan Safari versi terbaru. Memiliki kekuatan matematika semacam ini di CSS membuka banyak sekali kemungkinan. Dalam tutorial ini, saya pikir kita akan mencelupkan jari kaki kita ke dalam air untuk merasakan beberapa fungsi yang lebih baru: sin() dan cos().

Ada fungsi trigonometri lain dalam pipa โ€” termasuk tan() - jadi mengapa hanya fokus pada sin() dan cos()? Mereka kebetulan sempurna untuk ide yang ada dalam pikiran saya, yaitu menempatkan teks di sepanjang tepi lingkaran. Itu sudah dibahas di sini di CSS-Tricks kapan Chris berbagi pendekatan yang menggunakan mixin Sass. Itu enam tahun yang lalu, jadi mari kita berikan perawatan yang berdarah.

Inilah yang ada dalam pikiran saya. Sekali lagi, saat ini hanya didukung di Firefox dan Safari:

Jadi, ini tidak persis seperti kata-kata yang membentuk lingkaran, tetapi kami menempatkan karakter teks di sepanjang lingkaran untuk membentuk tampilan jam. Inilah beberapa markup yang dapat kita gunakan untuk memulai:

<div class="clock"> <div class="clock-face"> <time datetime="12:00">12</time> <time datetime="1:00">1</time> <time datetime="2:00">2</time> <time datetime="3:00">3</time> <time datetime="4:00">4</time> <time datetime="5:00">5</time> <time datetime="6:00">6</time> <time datetime="7:00">7</time> <time datetime="8:00">8</time> <time datetime="9:00">9</time> <time datetime="10:00">10</time> <time datetime="11:00">11</time> </div>
</div>

Selanjutnya, berikut adalah beberapa gaya super dasar untuk .clock-face wadah. Saya memutuskan untuk menggunakan <time> tandai dengan a datetime atribut. 

.clock { --_ow: clamp(5rem, 60vw, 40rem); --_w: 88cqi; aspect-ratio: 1; background-color: tomato; border-radius: 50%; container-type: inline; display: grid; height: var(--_ow); place-content: center; position: relative; width var(--_ow);
}

Saya mendekorasi sedikit di sana, tetapi hanya untuk mendapatkan bentuk dasar dan warna latar belakang untuk membantu kita melihat apa yang sedang kita lakukan. Perhatikan bagaimana kita menyimpan width nilai dalam a variabel CSS. Kami akan menggunakannya nanti. Sejauh ini tidak banyak yang bisa dilihat:

Lingkaran besar berwarna tomat dengan daftar vertikal angka 1-12 di sebelah kiri.

Sepertinya semacam eksperimen seni modern, bukan? Mari perkenalkan variabel baru, --_r, untuk menyimpan lingkaran radius, yang sama dengan setengah lebar lingkaran. Dengan cara ini, jika lebar (--_w) berubah, nilai radius (--_r) juga akan diperbarui โ€” berkat fungsi matematika CSS lainnya, calc():

.clock { --_w: 300px; --_r: calc(var(--_w) / 2); /* rest of styles */
}

Sekarang, sedikit matematika. Sebuah lingkaran adalah 360 derajat. Kami memiliki 12 label pada jam kami, jadi ingin menempatkan angka setiap 30 derajat (360 / 12). Di bidang matematika, sebuah lingkaran dimulai pada jam 3, jadi siang hari sebenarnya minus 90 derajat dari itu, yaitu 270 derajat (360 - 90).

Mari tambahkan variabel lain, --_d, yang dapat kita gunakan untuk mengatur a gelar nilai untuk setiap angka pada tampilan jam. Kita akan menaikkan nilai sebesar 30 derajat untuk melengkapi lingkaran kita:

.clock time:nth-child(1) { --_d: 270deg; }
.clock time:nth-child(2) { --_d: 300deg; }
.clock time:nth-child(3) { --_d: 330deg; }
.clock time:nth-child(4) { --_d: 0deg; }
.clock time:nth-child(5) { --_d: 30deg; }
.clock time:nth-child(6) { --_d: 60deg; }
.clock time:nth-child(7) { --_d: 90deg; }
.clock time:nth-child(8) { --_d: 120deg; }
.clock time:nth-child(9) { --_d: 150deg; }
.clock time:nth-child(10) { --_d: 180deg; }
.clock time:nth-child(11) { --_d: 210deg; }
.clock time:nth-child(12) { --_d: 240deg; }

Oke, sekarang saatnya mengotori tangan kita dengan sin() dan cos() fungsi! Yang ingin kami lakukan adalah menggunakannya untuk mendapatkan koordinat X dan Y untuk setiap angka sehingga kami dapat menempatkannya dengan benar di sekitar tampilan jam.

Rumus untuk koordinat X adalah radius + (radius * cos(degree)). Mari pasang itu ke yang baru --_x variabel:

--_x: calc(var(--_r) + (var(--_r) * cos(var(--_d))));

Rumus untuk koordinat Y adalah radius + (radius * sin(degree)). Kami memiliki apa yang perlu kami hitung bahwa:

--_y: calc(var(--_r) + (var(--_r) * sin(var(--_d))));

Ada beberapa hal tata graha yang perlu kita lakukan untuk menyetel angka, jadi mari beri gaya dasar pada angka untuk memastikan angka benar-benar diposisikan dan ditempatkan dengan koordinat kita:

.clock-face time { --_x: calc(var(--_r) + (var(--_r) * cos(var(--_d)))); --_y: calc(var(--_r) + (var(--_r) * sin(var(--_d)))); --_sz: 12cqi; display: grid; height: var(--_sz); left: var(--_x); place-content: center; position: absolute; top: var(--_y); width: var(--_sz);
}

Melihat --_sz, yang akan kita gunakan untuk width dan height dari angka dalam sekejap. Mari kita lihat apa yang kita miliki sejauh ini.

Lingkaran besar berwarna tomat dengan label nomor jam yang tidak terpusat di sepanjang tepinya.

Ini jelas lebih mirip jam! Lihat bagaimana pojok kiri atas setiap angka diposisikan di tempat yang benar di sekitar lingkaran? Kita perlu "mengecilkan" radius saat menghitung posisi setiap angka. Kita dapat mengurangi ukuran angka (--_sz) dari ukuran lingkaran (--_w), sebelum kita menghitung radius:

--_r: calc((var(--_w) - var(--_sz)) / 2);
Lingkaran besar berwarna tomat dengan label nomor jam di sepanjang tepinya yang membulat.

Jauh lebih baik! Mari ubah warnanya, agar terlihat lebih elegan:

Wajah jam putih dengan angka dengan latar belakang abu-abu gelap. Jam tidak memiliki lengan.

Kita bisa berhenti di sini! Kami mencapai tujuan menempatkan teks di sekitar lingkaran, bukan? Tapi apa itu jam tanpa lengan untuk menunjukkan jam, menit, dan detik?

Mari gunakan satu animasi CSS untuk itu. Pertama, mari tambahkan tiga elemen lagi ke markup kita,

<div class="clock"> <!-- after <time>-tags --> <span class="arm seconds"></span> <span class="arm minutes"></span> <span class="arm hours"></span> <span class="arm center"></span>
</div>

Kemudian beberapa markup umum untuk ketiga lengan. Sekali lagi, sebagian besar dari ini hanya memastikan lengan benar-benar diposisikan dan ditempatkan sesuai:

.arm { background-color: var(--_abg); border-radius: calc(var(--_aw) * 2); display: block; height: var(--_ah); left: calc((var(--_w) - var(--_aw)) / 2); position: absolute; top: calc((var(--_w) / 2) - var(--_ah)); transform: rotate(0deg); transform-origin: bottom; width: var(--_aw);
}

Kami akan menggunakan animasi yang sama untuk ketiga lengan:

@keyframes turn { to { transform: rotate(1turn); }
}

Satu-satunya perbedaan adalah waktu yang dibutuhkan masing-masing lengan untuk melakukan putaran penuh. Untuk lengan jam, dibutuhkan 12 jam untuk melakukan putaran penuh. Itu animation-duration properti hanya menerima nilai dalam milidetik dan detik. Mari kita tetap dengan detik, yaitu 43,200 detik (60 seconds * 60 minutes * 12 hours).

animation: turn 43200s infinite;

Dibutuhkan 1 jam untuk lengan menit untuk melakukan putaran penuh. Tapi kami ingin ini menjadi a animasi multi-langkah jadi gerakan antar lengan lebih terhuyung-huyung daripada linier. Kita memerlukan 60 langkah, satu untuk setiap menit:

animation: turn 3600s steps(60, end) infinite;

Grafik lengan detik is hampir sama sebagai lengan menit, tetapi durasinya adalah 60 detik, bukan 60 menit:

animation: turn 60s steps(60, end) infinite;

Mari perbarui properti yang kita buat dengan gaya umum:

.seconds { --_abg: hsl(0, 5%, 40%); --_ah: 145px; --_aw: 2px; animation: turn 60s steps(60, end) infinite;
}
.minutes { --_abg: #333; --_ah: 145px; --_aw: 6px; animation: turn 3600s steps(60, end) infinite;
}
.hours { --_abg: #333; --_ah: 110px; --_aw: 6px; animation: turn 43200s linear infinite;
}

Bagaimana jika kita ingin memulai pada waktu sekarang? Kami membutuhkan sedikit JavaScript:

const time = new Date();
const hour = -3600 * (time.getHours() % 12);
const mins = -60 * time.getMinutes();
app.style.setProperty('--_dm', `${mins}s`);
app.style.setProperty('--_dh', `${(hour+mins)}s`);

aku sudah menambahkan id="app" ke permukaan jam dan setel dua properti khusus baru di atasnya yang menyetel negatif animation-delay, seperti yang dilakukan Mate Marschalko ketika dia membagikan jam khusus CSS. itu getHours() metode JavaScipt Date objek menggunakan format 24 jam, jadi kami menggunakan remainder operator untuk mengubahnya menjadi format 12 jam.

Di CSS, kita perlu menambahkan animation-delay demikian juga:

.minutes { animation-delay: var(--_dm, 0s); /* other styles */
} .hours { animation-delay: var(--_dh, 0s); /* other styles */
}

Hanya satu lagi. Menggunakan CSS @supports dan properti yang telah kami buat, kami dapat menyediakan fallback ke browser yang tidak mendukung sin() dan cos(). (Terima kasih, Temani Afif!):

@supports not (left: calc(1px * cos(45deg))) {
  time {
    left: 50% !important;
    top: 50% !important;
    transform: translate(-50%,-50%) rotate(var(--_d)) translate(var(--_r)) rotate(calc(-1*var(--_d)))
  }
}

Dan, voila! Jam kita sudah selesai! Inilah demo terakhir sekali lagi. Sekali lagi, saat ini hanya didukung di Firefox dan Safari.

apa lagi yang bisa kita lakukan?

Hanya bermain-main di sini, tapi kita bisa dengan cepat mengubah jam kita menjadi galeri gambar melingkar dengan mengganti <time> tag dengan <img> lalu perbarui lebar (--_w) dan jari-jari (--_r) nilai:

Mari kita coba satu lagi. Saya sebutkan sebelumnya bagaimana jam itu terlihat seperti eksperimen seni modern. Kita dapat mempelajarinya dan membuat ulang pola yang saya lihat di poster (sayangnya tidak saya beli) di galeri seni tempo hari. Seingat saya, itu disebut "Bulan" dan terdiri dari sekumpulan titik yang membentuk lingkaran.

Sebuah lingkaran besar terbentuk dari sekumpulan lingkaran kecil berisi berbagai warna warna tanah.

Kami akan menggunakan unordered list kali ini karena lingkaran tidak mengikuti urutan tertentu. Kami bahkan tidak akan memasukkan semua item daftar ke dalam markup. Sebagai gantinya, mari masukkan mereka dengan JavaScript dan tambahkan beberapa kontrol yang bisa kita gunakan untuk memanipulasi hasil akhir.

Kontrol adalah input jangkauan (<input type="range">) yang akan kita bungkus dalam <form> dan mendengarkan untuk input peristiwa.

<form id="controls"> <fieldset> <label>Number of rings <input type="range" min="2" max="12" value="10" id="rings" /> </label> <label>Dots per ring <input type="range" min="5" max="12" value="7" id="dots" /> </label> <label>Spread <input type="range" min="10" max="40" value="40" id="spread" /> </label> </fieldset>
</form>

Kami akan menjalankan metode ini pada "input", yang akan membuat banyak <li> unsur dengan derajat (--_d) variabel yang kami gunakan sebelumnya diterapkan ke masing-masing. Kami juga dapat menggunakan kembali variabel radius kami (--_r).

Saya juga ingin titik-titik menjadi warna yang berbeda. Jadi, mari kita mengacak (yah, tidak sama sekali diacak) nilai warna HSL untuk setiap item daftar dan menyimpannya sebagai variabel CSS baru, --_bgc:

const update = () => { let s = ""; for (let i = 1; i <= rings.valueAsNumber; i++) { const r = spread.valueAsNumber * i; const theta = coords(dots.valueAsNumber * i); for (let j = 0; j < theta.length; j++) { s += `<li style="--_d:${theta[j]};--_r:${r}px;--_bgc:hsl(${random( 50, 25 )},${random(90, 50)}%,${random(90, 60)}%)"></li>`; } } app.innerHTML = s;
}

Grafik random() metode mengambil nilai dalam rentang angka yang ditentukan:

const random = (max, min = 0, f = true) => f ? Math.floor(Math.random() * (max - min) + min) : Math.random() * max;

Dan itu saja. Kami menggunakan JavaScript untuk merender markup, tetapi segera setelah dirender, kami tidak terlalu membutuhkannya. Itu sin() dan cos() fungsi membantu kami memposisikan semua titik di tempat yang tepat.

Pesan terakhir

Menempatkan sesuatu di sekitar lingkaran adalah contoh yang cukup mendasar untuk menunjukkan kekuatan seperti fungsi trigonometri sin() dan cos(). Tapi itu benar-benar keren bahwa kita mendapatkan fitur CSS modern yang memberikan solusi baru untuk solusi lama. Saya yakin kita akan melihat kasus penggunaan yang jauh lebih menarik, kompleks, dan kreatif, terutama karena dukungan browser datang ke Chrome dan Edge.

Stempel Waktu:

Lebih dari Trik CSS

Serbet

Node Sumber: 1016208
Stempel Waktu: Agustus 11, 2021