Baru-baru ini saya telah menyegarkan semula grafik animasi di tapak web saya dengan tema baharu dan sekumpulan watak perintis, mempraktikkan banyak teknik yang saya kongsikan dalam siri ini. Beberapa animasi saya berubah penampilan apabila seseorang berinteraksi dengan mereka atau pada masa yang berbeza dalam sehari.
Warna dalam grafik di atas halaman blog saya berubah dari pagi hingga malam setiap hari. Kemudian, terdapat mod salji, yang menambah warna sejuk dan tema musim sejuk, ihsan lapisan tindanan dan mod campuran.
Semasa mengerjakan perkara ini, saya mula tertanya-tanya sama ada nilai warna relatif CSS boleh memberi saya lebih kawalan sambil turut memudahkan proses. Nota: Dalam tutorial ini, saya akan menumpukan pada nilai warna relatif dan ruang warna OKLCH untuk grafik dan animasi bertema. Jika anda ingin mendalami warna relatif, Ahmad Shadeed mencipta panduan interaktif yang hebat. Bagi ruang warna, gamut dan OKLCH, Geoff Graham kami sendiri menulis tentangnya.
Penggunaan berulang elemen adalah kunci. Latar belakang digunakan semula apabila boleh, dengan zum dan tindanan membantu membina adegan baharu daripada karya seni yang sama. Ia lahir dari keperluan, tetapi ia juga menggalakkan pemikiran dari segi siri dan bukannya adegan individu. Masalah Mengemas kini Palet Warna Secara Manual Mari terus kepada cabaran saya. Dalam Toon Titles seperti ini — berdasarkan episod Yogi Bear Show 1959 “Lullabye-Bye Bear” — dan kerja saya secara amnya, palet terhad kepada beberapa warna terpilih.
Saya mencipta warna dan warna daripada apa yang saya panggil warna "asas" saya untuk mengembangkan palet tanpa menambah lebih banyak warna.
Dalam Sketch, saya bekerja dalam ruang warna HSL, jadi proses ini melibatkan peningkatan atau pengurangan nilai kecerahan warna asas saya. Sejujurnya, ia bukanlah satu tugas yang sukar - tetapi memilih warna asas yang berbeza memerlukan mencipta set warna dan warna baharu. Melakukannya secara manual, berulang kali, dengan cepat menjadi susah payah.
Saya menyebut HSL — H (warna), S (tepu), dan L (ringan) — ruang warna, tetapi itu hanyalah salah satu daripada beberapa cara untuk menerangkan warna. RGB — R (merah), G (hijau), B (biru) — mungkin yang paling biasa, sekurang-kurangnya dalam bentuk Hexnya. Terdapat juga LAB — L (lightness), A (hijau-merah), B (biru-kuning) — dan yang lebih baharu, tetapi kini disokong secara meluas LCH — L (lightness), C (chroma), H (rona) — dalam bentuk OKLCH. Dengan LCH — khususnya OKLCH dalam CSS — saya boleh melaraskan nilai kecerahan warna asas saya.
Atau saya boleh mengubah kromanya. Kroma LCH dan ketepuan HSL kedua-duanya menggambarkan keamatan atau kekayaan warna, tetapi mereka melakukannya dengan cara yang berbeza. LCH memberi saya julat yang lebih luas dan campuran yang lebih boleh diramal antara warna.
Saya juga boleh mengubah rona untuk mencipta palet warna yang berkongsi kecerahan dan nilai kroma yang sama. Dalam kedua-dua HSL dan LCH, spektrum warna bermula pada merah, bergerak melalui hijau dan biru, dan kembali kepada merah.
Mengapa OKLCH Mengubah Cara Saya Berfikir Mengenai Warna Sokongan penyemak imbas untuk ruang warna OKLCH kini meluas, walaupun alat reka bentuk — termasuk Sketch — tidak mengikutinya. Nasib baik, itu tidak sepatutnya menghalang anda daripada menggunakan OKLCH. Penyemak imbas dengan senang hati akan menukar nilai Hex, HSL, LAB dan RGB kepada OKLCH untuk anda. Anda boleh menentukan sifat tersuai CSS dengan warna asas dalam mana-mana ruang, termasuk Hex: /* Warna asas */ --asas: #5accd6;
Sebarang warna yang diperoleh daripadanya akan ditukar kepada OKLCH secara automatik: --foundation-light: oklch(dari var(--foundation) [...]; } --foundation-mid: oklch(dari var(--foundation) [...]; } --foundation-dark: oklch(dari var(--foundation) [...]; }
Warna Relatif Sebagai Sistem Reka Bentuk Fikirkan warna relatif sebagai berkata: "Ambil warna ini, ubah suai, kemudian berikan saya hasilnya." Terdapat dua cara untuk melaraskan warna: perubahan mutlak dan perubahan berkadar. Mereka kelihatan serupa dalam kod, tetapi berkelakuan sangat berbeza sebaik sahaja anda mula menukar warna asas. Memahami perbezaan itu adalah perkara yang boleh menukar menggunakan warna relatif kepada sistem. /* Warna asas */ --asas: #5accd6;
Sebagai contoh, nilai kecerahan warna asas saya ialah 0.7837, manakala versi yang lebih gelap mempunyai nilai 0.5837. Untuk mengira perbezaan, saya menolak nilai yang lebih rendah daripada yang lebih tinggi dan menggunakan hasilnya menggunakan fungsi calc(): --asas-gelap: oklch(dari var(--foundation) calc(l - 0.20) c h);
Untuk mencapai warna yang lebih terang, saya tambahkan perbezaannya: --cahaya-asas: oklch(dari var(--foundation) calc(l + 0.10) c h);
Chromapelarasan mengikut proses yang sama. Untuk mengurangkan keamatan warna asas saya daripada 0.1035 kepada 0.0035, saya menolak satu nilai daripada yang lain: oklch(dari var(--foundation) l calc(c - 0.10) h);
Untuk mencipta palet rona, saya mengira perbezaan antara nilai rona warna asas saya (200) dan rona baharu saya (260): oklch(dari var(--foundation) l c calc(h + 60));
Pengiraan tersebut adalah mutlak. Apabila saya menolak amaun tetap, saya dengan berkesan berkata, "Sentiasa tolak sebanyak ini." Perkara yang sama berlaku apabila menambah nilai tetap: calc(c - 0.10) calc(c + 0.10)
Saya mempelajari had pendekatan ini dengan cara yang sukar. Apabila saya bergantung pada penolakan nilai kroma tetap, warna runtuh ke arah kelabu sebaik sahaja saya menukar asas. Palet yang berfungsi untuk satu warna runtuh untuk warna lain. Pendaraban berkelakuan berbeza. Apabila saya mendarab kroma, saya memberitahu penyemak imbas: "Kurangkan keamatan warna ini dengan perkadaran." Hubungan antara warna kekal utuh, walaupun asas berubah: calc(c * 0.10)
Saya Mengalihkannya, Skalakannya, Putar Ia Peraturan
Gerakkan ringan (tambah atau tolak), Skala kroma (darab), Putar rona (tambah atau tolak darjah).
Saya skala kroma kerana saya mahu perubahan keamatan kekal berkadar dengan warna asas. Hubungan rona adalah bergilir-gilir, jadi penggandaan rona tidak masuk akal. Ringan adalah persepsi dan mutlak — mendarabkannya selalunya menghasilkan hasil yang ganjil.
Daripada Satu Warna Kepada Keseluruhan Tema Warna relatif membolehkan saya mentakrifkan warna asas dan menjana setiap warna lain yang saya perlukan — isian, pukulan, hentian kecerunan, bayang-bayang — daripadanya. Pada ketika itu, warna berhenti menjadi palet dan mula menjadi sistem. Ilustrasi SVG cenderung untuk menggunakan semula beberapa warna yang sama merentasi isian, pukulan dan kecerunan. Warna relatif membolehkan anda mentakrifkan perhubungan tersebut sekali dan menggunakannya semula di mana-mana — sama seperti animator menggunakan semula latar belakang untuk mencipta adegan baharu.
Tukar warna asas sekali, dan setiap warna terbitan dikemas kini secara automatik, tanpa mengira semula apa-apa dengan tangan. Di luar grafik animasi, saya boleh menggunakan pendekatan yang sama ini untuk menentukan warna bagi keadaan elemen interaktif seperti butang dan pautan. Warna asas yang saya gunakan dalam Tajuk Toon "Lullabye-Bye Bear" saya ialah biru yang kelihatan seperti cyan. Latar belakang ialah kecerunan jejari antara asas saya dan versi yang lebih gelap.
Untuk mencipta versi alternatif dengan mood yang berbeza, saya hanya perlu menukar warna asas: --asas: #5accd6; --grad-end: var(--foundation); --grad-start: oklch(dari var(--foundation) calc(l - 0.2357) calc(c * 0.833) h);
Untuk mengikat sifat tersuai tersebut pada kecerunan SVG saya tanpa menduplikasi nilai warna, saya menggantikan nilai warna henti berkod keras dengan gaya sebaris:
Seterusnya, saya perlu memastikan Teks Toon saya sentiasa berbeza dengan warna asas yang saya pilih. Putaran rona 180 darjah menghasilkan warna pelengkap yang pasti muncul — tetapi boleh bergetar dengan tidak selesa: .text-light { isi: oklch(dari var(--foundation) l c calc(h + 180)); }
Anjakan 90° menghasilkan warna sekunder yang terang tanpa pelengkap sepenuhnya: .text-light { isi: oklch(dari var(--foundation) l c calc(h - 90)); }
Rekreasi saya mengenai Quick Draw McGraw 1959 Toon Title "El Kabong" menggunakan teknik yang sama tetapi dengan palet yang lebih pelbagai. Sebagai contoh, terdapat satu lagi kecerunan jejari antara warna asas dan warna yang lebih gelap.
Bangunan dan pokok di latar belakang hanyalah warna yang berbeza dengan warna asas yang sama. Untuk laluan tersebut, saya memerlukan dua warna isian tambahan: .bg-mid { isi: oklch(dari var(--foundation) calc(l - 0.04) calc(c * 0.91) h); }
.bg-gelap { isi: oklch(dari var(--foundation) calc(l - 0.12) calc(c * 0.64) h); }
Apabila Asas Mula Bergerak
Setakat ini, semua yang saya tunjukkan adalah statik. Walaupun apabila seseorang menggunakan pemilih warna untuk menukar warna asas, perubahan itu berlaku serta-merta. Tetapi grafik animasi jarang diam — petunjuknya ada pada namanya. Jadi, jika warna adalah sebahagian daripada sistem, tiada sebab ia tidak boleh bernyawa juga.
Untuk menghidupkan warna asas, saya perlu membahagikannya terlebih dahulu kepada saluran OKLCHnya— kecerahan, kroma dan rona. Tetapi ada langkah tambahan yang penting: Saya perlu mendaftarkan nilai tersebut sebagai sifat tersuai yang ditaip. Tetapi apakah maksudnya?
Secara lalai, penyemak imbas tidak mengetahui sama ada nilai sifat tersuai CSS mewakili warna, panjang, nombor atau sesuatu yang lain sepenuhnya. Ini selalunya bermakna mereka tidak boleh diinterpolasi dengan lancar semasa animasi, dan melompat dari satu nilai ke nilai seterusnya.
Mendaftarkan harta tersuai memberitahu penyemak imbas jenis nilai yang diwakilinya dan cara ia harus bertindak dari semasa ke semasa. Dalam kes ini, saya mahu penyemak imbas menganggap saluran warna saya sebagai nombor supaya ia boleh dianimasikan dengan lancar.
@property --f-l {
sintaks: "
@property --f-c {
sintaks: "
@property --f-h {
sintaks: "
Setelah didaftarkan, sifat tersuai ini berkelakuan seperti CSS asli. Penyemak imbas boleh menginterpolasinya bingkai demi bingkai. Saya kemudian membina semula warna asas dari saluran tersebut: --asas: oklch(var(--f-l) var(--f-c) var(--f-h));
Ini menjadikan warna asas menjadi boleh animasi, sama seperti nilai berangka lain. Berikut ialah animasi "pernafasan" mudah yang perlahan-lahan mengalihkan cahaya dari semasa ke semasa: @keyframes bernafas { 0%, 100% { --f-l: 0.36; } 50% { --f-l: 0.46; } }
.toon-title { animasi: bernafas 10s kemudahan masuk-keluar tanpa had; }
Oleh kerana setiap warna lain dalam isian, kecerunan dan lejang berasal daripada --foundation, semuanya bernyawa bersama-sama dan tiada apa yang perlu dikemas kini secara manual. Satu Warna Animasi, Banyak Kesan Pada permulaan proses ini, saya tertanya-tanya sama ada nilai warna relatif CSS boleh menawarkan lebih banyak kemungkinan sambil menjadikannya lebih mudah untuk dilaksanakan. Saya baru-baru ini menambahkan latar belakang lombong emas baharu pada halaman hubungan tapak web saya, dan lelaran pertama termasuk lampu minyak yang bercahaya dan berayun.
Saya ingin meneroka bagaimana menganimasikan warna relatif CSS boleh menjadikan bahagian dalam lombong lebih realistik dengan mewarnakannya dengan warna dari lampu. Saya mahu mereka mempengaruhi dunia di sekeliling mereka, seperti cahaya sebenar. Jadi, daripada menganimasikan pelbagai warna, saya membina sistem pencahayaan kecil yang menghidupkan satu warna sahaja.
Tugas pertama saya ialah meletakkan lapisan tindanan antara latar belakang dan lampu saya:
Saya menggunakan mod campuran-campuran: warna kerana ia mewarnakan apa yang ada di bawahnya sambil mengekalkan pencahayaan asas. Oleh kerana saya hanya mahu tindanan kelihatan apabila animasi dihidupkan, saya membuat ikut serta tindanan: .svg-mine #overlay { paparan: tiada; }
@media ( prefers-reduced-motion: no-preference) { .svg-mine[data-animations=on] #overlay { paparan: blok; kelegapan: 0.5; } }
Tindanan telah dipasang, tetapi belum disambungkan ke lampu. Saya memerlukan sumber cahaya. Lampu saya ringkas, dan setiap satu mengandungi elemen bulatan yang saya kaburkan dengan penapis. Penapis menghasilkan kabur yang sangat lembut pada keseluruhan bulatan.
Daripada menghidupkan tindanan dan lampu secara berasingan, saya menganimasikan satu token warna "nyalaan" tunggal dan memperoleh segala-galanya daripada itu. Mula-mula, saya mendaftarkan tiga sifat tersuai yang ditaip untuk saluran OKLCH:
@property --fl-l {
sintaks: "
Saya menghidupkan saluran tersebut, dengan sengaja menolak beberapa bingkai ke arah oren supaya kerlipan itu berbunyi dengan jelas sebagai cahaya api:
@keyframes nyala { 0%, 100% { --fl-l: 0.86; --fl-c: 0.12; --fl-h: 95; } 6% { --fl-l: 0.91; --fl-c: 0.10; --fl-h: 92; } 12% { --fl-l: 0.83; --fl-c: 0.14; --fl-h: 100; } 18% { --fl-l: 0.88; --fl-c: 0.11; --fl-h: 94; } 24% { --fl-l: 0.82; --fl-c: 0.16; --fl-h: 82; } 30% { --fl-l: 0.90; --fl-c: 0.12; --fl-h: 90; } 36% { --fl-l: 0.79; --fl-c: 0.17; --fl-h: 76; } 44% { --fl-l: 0.87; --fl-c: 0.12; --fl-h: 96; } 52% { --fl-l: 0.81; --fl-c: 0.15; --fl-h: 102; } 60% { --fl-l: 0.89; --fl-c: 0.11; --fl-h: 93; } 68% { --fl-l: 0.83; --fl-c: 0.16; --fl-h: 85; } 76% { --fl-l: 0.91; --fl-c: 0.10; --fl-h: 91; } 84% { --fl-l: 0.85; --fl-c: 0.14; --fl-h: 98; } 92% {--fl-l: 0.80; --fl-c: 0.17; --fl-h: 74; } }
Kemudian saya skop animasi itu ke SVG, jadi pembolehubah yang dikongsi tersedia untuk kedua-dua lampu dan tindanan saya:
@media ( prefers-reduced-motion: no-preference) { .svg-mine[data-animations=on] { animasi: nyalaan 3.6s linear tak terhingga; pengasingan: mengasingkan;
/* Bina warna nyalaan daripada saluran animasi */ --api: oklch(var(--fl-l) var(--fl-c) var(--fl-h));
/* Warna lampu berasal daripada nyalaan */ --teras lampu: oklch(daripada var(--nyalaan) calc(l + 0.05) calc(c * 0.70) h);
/* Tindanan tindanan yang diperoleh daripada nyalaan yang sama */ --overlay-tint: oklch(dari var(--flame) calc(l + 0.06) calc(c * 0.65) calc(h - 10)); } }
Akhirnya, saya menggunakan warna terbitan tersebut pada lampu bercahaya dan lapisan yang mempengaruhinya: @media ( prefers-reduced-motion: no-preference) { .svg-mine[data-animations=on] #mine-lamp-1 > bulatan, .svg-mine[data-animations=on] #mine-lamp-2 > circle { isi: var(--lampu-teras); }
.svg-mine[data-animations=on] #overlay { paparan: blok; isi: var(--tint-tinting); kelegapan: 0.5; } }
Apabila nyalaan beralih ke oren, lampu menjadi panas, dan pemandangan menjadi hangat dengannya. Apabila api sejuk, semuanya mendap bersama. Bahagian yang terbaik ialah tiada apa yang ditulis secara manual. Jika saya menukar warna asas atau mengubah julat animasi nyalaan, keseluruhan sistem pencahayaan dikemas kini secara serentak. Anda boleh melihat keputusan akhir di laman web saya. Guna Semula, Guna Semula, Dilawati Semula Animator Hanna-Barbera tersebut terpaksa menggunakan semula elemen kerana keperluan, tetapi saya menggunakan semula warna kerana ia menjadikan kerja saya lebih konsisten dan lebih mudah untuk diselenggara. Nilai warna relatif CSS membolehkan saya:
Tentukan satu warna asas, Terangkan bagaimana warna lain berkaitan dengannya, Gunakan semula perhubungan tersebut di mana-mana sahaja, dan Animasikan sistem dengan menukar satu nilai.
Warna relatif bukan sahaja memudahkan tema. Ia menggalakkan cara berfikir di mana warna, seperti gerakan, adalah disengajakan — dan apabila menukar satu nilai boleh mengubah keseluruhan pemandangan tanpa menulis semula kerja di bawahnya.