


Memaku kontras yang sempurna antara teks cahaya dan imej latar belakang
Pernahkah anda menemui teks ringan di laman web yang ditumpukan pada imej latar belakang cahaya? Jika anda telah menemuinya, anda akan tahu betapa sukarnya membaca. Salah satu cara yang biasa untuk mengelakkan ini ialah menggunakan lapisan telus. Tetapi ini menimbulkan persoalan penting: berapa tinggi ketelusan overlay? Kami tidak selalu berurusan dengan saiz fon, ketebalan, dan warna yang sama, dan tentu saja, gambar yang berbeza juga akan menghasilkan kontras yang berbeza.
Cuba untuk menghapuskan masalah kontras teks yang lemah pada imej latar belakang, sama seperti bermain permainan goblin. Daripada meneka, gunakan HTML<canvas></canvas>
Dan beberapa kaedah matematik untuk menyelesaikan masalah ini.
Seperti ini:
Kita boleh mengatakan "Masalahnya diselesaikan!" Dan kemudian tamatkan artikel ini. Tetapi apa keseronokan ini? Apa yang saya ingin tunjukkan adalah bagaimana alat ini berfungsi supaya anda dapat menguasai cara baru untuk menangani masalah biasa ini.
merancang
Pertama, mari kita jelaskan matlamat kita. Kami berkata bahawa kami mahu memaparkan teks yang boleh dibaca pada imej latar belakang, tetapi apa sebenarnya maksud "boleh dibaca"? Untuk tujuan kami, kami akan menggunakan definisi WCAG mengenai kebolehbacaan peringkat AA, yang menyatakan bahawa terdapat keperluan untuk perbezaan yang mencukupi antara teks dan warna latar belakang supaya satu warna adalah 4.5 kali lebih cerah daripada yang lain.
Mari kita pilih warna teks, imej latar belakang, dan warna overlay sebagai titik permulaan. Memandangkan input ini, kami ingin mencari tahap kelegapan lapisan yang menjadikan teks boleh dibaca tanpa menyembunyikan imej sehingga imej itu sukar dilihat. Untuk merumitkan perkara sedikit, kami akan menggunakan gambar yang mempunyai warna gelap dan cahaya, dan pastikan overlay mengambilnya.
Hasil akhir kami akan menjadi nilai yang kami boleh memohon kepada sifat Opacity CSS Overlay, yang menjadikan teks 4.5 kali lebih cerah daripada latar belakang.
Untuk mencari kelegapan overlay terbaik, kami akan melakukan empat langkah:
- Kami memasukkan imej ke HTML
<canvas></canvas>
Ini akan membolehkan kita membaca warna setiap piksel dalam gambar. - Kami akan menemui piksel dalam gambar yang paling tidak berbeza dengan teks.
- Seterusnya, kami akan menyediakan formula pencampuran warna yang boleh kita gunakan untuk menguji kesan tahap kelegapan yang berbeza pada warna piksel itu.
- Akhirnya, kami akan menyesuaikan kelegapan lapisan sehingga kontras teks mencapai matlamat pembacaan. Ini tidak akan meneka secara rawak - kami akan menggunakan teknik carian binari untuk mempercepatkan proses ini.
Mari mulakan!
Langkah 1: Baca warna gambar dari kanvas
Kanvas membolehkan kita "membaca" warna yang terkandung dalam imej. Untuk melakukan ini, kita perlu "melukis" imej ke<canvas></canvas>
Pada elemen, kemudian gunakan kaedah getImageData()
konteks kanvas (CTX) untuk menghasilkan senarai warna imej.
fungsi getImagePixelColorSusingCanvas (imej, kanvas) { // Konteks kanvas (biasanya disingkat sebagai ctx) adalah objek yang mengandungi banyak fungsi untuk mengawal kanvas anda const ctx = canvas.getContext ('2d'); // Lebar boleh menjadi apa -apa nilai, jadi saya memilih 500 kerana ia cukup besar untuk menangkap butiran, tetapi cukup kecil untuk membuat pengiraan lebih cepat. canvas.width = 500; // pastikan kanvas sepadan dengan skala imej kanvas.height = (image.height / image.width) * canvas.width; // Dapatkan pengukuran imej dan kanvas supaya kita dapat menggunakannya dalam langkah seterusnya ConstoureMageCoordinates = [0, 0, image.width, image.height]; const destinationCanvascoordinates = [0, 0, canvas.width, canvas.height]; // lukisan kanvas 'berfungsi dengan memetakan pengukuran imej kami ke kanvas yang kami ingin lukiskannya di ctx.drawimage ( gambar, ... sourceimagecoordinates, ... destinasiCanvascoordinates ); // Ingatlah bahawa getimageData hanya berfungsi dengan imej dengan sumber yang sama atau silang asal yang diaktifkan. // https://developer.mozilla.org/en-us/docs/web/html/cors_enabled_image const ImagePixelColors = ctx.getimagedata (... destinasiCanvasCoordinates); kembali imagePixelColors; }
Kaedah getImageData()
memberikan kami senarai nombor yang mewakili warna setiap piksel. Setiap piksel diwakili oleh empat nombor: merah, hijau, biru, dan kelegapan (juga dikenali sebagai "alpha". Mengetahui ini, kita boleh melangkah melalui senarai piksel dan mencari apa -apa maklumat yang kita perlukan. Ini akan sangat berguna dalam langkah seterusnya.
Langkah 2: Cari piksel dengan sebaliknya
Sebelum itu, kita perlu tahu cara mengira kontras. Kami akan menulis fungsi yang dipanggil getContrast()
yang mengambil dua warna dan output nombor yang menunjukkan tahap perbezaan antara kedua -dua warna. Semakin tinggi angka -angka, semakin baik kontras dan lebih baik pembacaan.
Apabila saya mula meneliti warna projek ini, saya menjangka dapat mencari formula yang mudah. Ternyata terdapat beberapa langkah.
Untuk mengira perbezaan antara dua warna, kita perlu mengetahui tahap kecerahan mereka, yang pada dasarnya kecerahan (Stacie Arellano mempunyai pandangan yang mendalam pada kecerahan, yang patut dilihat).
Terima kasih kepada W3C, kami tahu formula untuk mengira kontras menggunakan kecerahan:
const kontras = (LighterColorluminance 0.05) / (DarkerColorluminance 0.05);
Mendapatkan kecerahan warna bermakna kita perlu menukar warna dari nilai RGB 8-bit biasa yang digunakan pada rangkaian (di mana setiap warna adalah 0-255) kepada apa yang disebut RGB linear. Kita perlu melakukan ini kerana kecerahan tidak meningkat sama rata dengan perubahan warna. Kita perlu menukar warna ke format di mana kecerahan berubah sama rata dengan warna. Ini membolehkan kita mengira kecerahan dengan betul. Begitu juga, W3C memberikan bantuan di sini:
const luminance = (0.2126 * getLinearrgb (r) 0.7152 * getLinearrgb (g) 0.0722 * getLinearrgb (b));
Tetapi tunggu, ada lagi! Untuk menukar 8-bit RGB (0 hingga 255) kepada RGB linear, kita perlu melalui apa yang dipanggil standard RGB (juga dikenali sebagai SRGB), yang mempunyai nisbah 0 hingga 1.
Oleh itu, prosesnya adalah seperti berikut:
<code>8位RGB → 标准RGB → 线性RGB → 亮度</code>
Sebaik sahaja kita mempunyai kecerahan kedua -dua warna yang kita mahu bandingkan, kita dapat menggantikan nilai kecerahan ke dalam formula untuk mendapatkan perbezaan antara warna masing -masing.
// getContrast adalah satu -satunya fungsi yang kita perlukan untuk berinteraksi secara langsung. // Selebihnya fungsi adalah langkah tambahan pertengahan. fungsi getContrast (color1, color2) { const color1_luminance = getLuminance (color1); const color2_luminance = getLuminance (color2); const LighterColorLuminance = Math.Max (color1_luminance, color2_luminance); consterColorLuminance = Math.min (color1_luminance, color2_luminance); const kontras = (LighterColorluminance 0.05) / (DarkerColorluminance 0.05); pulangan kontras; } fungsi getLuminance ({r, g, b}) { pulangan (0.2126 * getLinearrgb (r) 0.7152 * getLinearrgb (g) 0.0722 * getLinearrgb (b)); } fungsi getLinearrgb (primaryColor_8bit) { // Pertama Tukar dari 8-bit RGB (0-255) ke standard RGB (0-1) const primaryColor_srgb = convert_8bit_rgb_to_standard_rgb (primaryColor_8bit); // kemudian tukar dari srgb ke linear rgb supaya kita boleh menggunakannya untuk mengira kecerahan const primaryColor_rgb_linear = convert_standard_rgb_to_linear_rgb (primarycolor_srgb); kembali primarycolor_rgb_linear; } fungsi convert_8bit_rgb_to_standard_rgb (primaryColor_8bit) { kembali primarycolor_8bit / 255; } fungsi convert_standard_rgb_to_linear_rgb (primaryColor_srgb) { const primaryColor_Linear = primaryColor_Srgb <p> Sekarang kita dapat mengira kontras, kita perlu melihat imej pada langkah sebelumnya dan meleleh melalui setiap piksel untuk membandingkan perbezaan antara warna piksel dan warna teks latar depan. Apabila kita melintasi piksel imej, kita akan mengesan kontras yang paling teruk (paling rendah) setakat ini, dan apabila kita sampai ke hujung gelung, kita akan mengetahui warna dengan kontras yang paling teruk dalam imej.</p><pre class="brush:php;toolbar:false"> fungsi getWorstContrastColoriniMage (TextColor, ImagePixelColors) { Biarkan WorstContrastColoriniMage; Biarkan WorstContrast = Infinity; // Ini memastikan bahawa kita tidak bermula dengan nilai yang terlalu rendah untuk (biarkan i = 0; i <imagepixelcolors.data.length i="4)" const r="ImagePixelColors.data" g="ImagePixelColors.data" b="ImagePixelColors.data" imagepixelcolor="{r," kontras="getContrast" jika worstcontrast="kontras;" worstcontrastcolorinimage="ImagePixelColor;" kembali><p></p> <h3 id="Langkah-Sediakan-formula-pencampuran-warna-untuk-menguji-tahap-kelegapan-overlay"> Langkah 3: Sediakan formula pencampuran warna untuk menguji tahap kelegapan overlay</h3> <p></p> <p> Sekarang kita tahu warna dengan kontras yang paling teruk dalam imej kita, langkah seterusnya adalah untuk menentukan betapa tinggi ketelusan overlay harus dan melihat bagaimana ini akan mengubah kontras dengan teks.</p> <p></p> <p> Apabila saya mula -mula melaksanakan ini, saya menggunakan kanvas berasingan untuk mencampur warna dan membaca hasilnya. Walau bagaimanapun, terima kasih kepada artikel Ana Tudor mengenai ketelusan, saya kini tahu terdapat formula yang mudah untuk mengira warna yang dihasilkan selepas mencampurkan warna asas dengan lapisan telus.</p> <p></p> <p> Untuk setiap saluran warna (merah, hijau, dan biru), kami akan menggunakan formula ini untuk mendapatkan warna yang dicampur:</p> <p> Warna campuran = warna asas (warna bertindih - warna asas) * kelegapan bertindih</p> <p></p> <p> Jadi, dalam kod, ini akan kelihatan seperti ini:</p> <pre class="brush:php;toolbar:false"> fungsi mixcolors (basecolor, overlaycolor, overlayopacity) { const mixedColor = { r: basecolor.r (overlaycolor.r - basecolor.r) * overlayopacity, g: basecolor.g (overlaycolor.g - basecolor.g) * overlayopacity, b: basecolor.b (overlaycolor.b - basecolor.b) * overlayopacity, } kembali campuran campuran; }
Sekarang kita boleh mencampur warna, kita boleh menguji kontras apabila menggunakan nilai kelegapan overlay.
fungsi getTextContrastWithimagePlusOverlay ({TextColor, overlayColor, ImagePixelColor, overlayopacity}) { const ColorOfImagePixelPlusOverlay = mixColors (ImagePixelColor, overlayColor, overlayopacity); const kontras = getContrast (textColor, colorOfImagePixelPlusOverlay); pulangan kontras; }
Dengan ini kita mempunyai semua alat yang kita perlukan untuk mencari kelegapan overlay terbaik!
Langkah 4: Cari kelegapan Overlay yang mencapai sasaran kontras
Kita boleh menguji kelegapan overlay dan melihat bagaimana ini akan mempengaruhi perbezaan antara teks dan imej. Kami akan mencuba pelbagai tahap kelegapan yang berbeza sehingga kami dapati nilai yang mencapai kontras sasaran, di mana teksnya adalah 4.5 kali lebih cerah daripada latar belakang. Ini mungkin terdengar gila, tetapi jangan risau; Kami tidak akan meneka secara rawak. Kami akan menggunakan carian binari, satu proses yang membolehkan kami dengan cepat menyempitkan set jawapan yang mungkin sehingga kami mendapat hasil yang tepat.
Inilah cara kerja carian binari:
<code>- 在中间猜测。 - 如果猜测过高,我们将消除答案的上半部分。太低了吗?我们将改为消除下半部分。 - 在新的范围中间猜测。 - 重复此过程,直到我们得到一个值。我碰巧有一个工具可以展示它是如何工作的:在这种情况下,我们试图猜测一个介于0和1之间的不透明度值。因此,我们将从中间猜测,测试结果对比度是太高还是太低,消除一半的选项,然后再次猜测。如果我们将二分查找限制为八次猜测,我们将立即得到一个精确的答案。在我们开始搜索之前,我们需要一种方法来检查是否根本需要叠加层。我们根本不需要优化我们不需要的叠加层! ```javascript function isOverlayNecessary(textColor, worstContrastColorInImage, desiredContrast) { const contrastWithoutOverlay = getContrast(textColor, worstContrastColorInImage); return contrastWithoutOverlay </code>
Sekarang kita boleh menggunakan carian binari untuk mencari kelegapan overlay yang terbaik:
fungsi findOptimaloverlayOpacity (TextColor, overlayColor, WorstContrastColoriniMage, DesiredContrast) { // Sekiranya kontras cukup baik, kita tidak perlu melayari, // Jadi kita boleh melangkau selebihnya. const isOverlayNessary = isOverlayNessary (TextColor, WorstContrastColoriniMage, DesiredContrast); jika (! isoverlaynessary) { kembali 0; } const opacityguessrange = { Lowerbound: 0, Titik tengah: 0.5, Upperbound: 1, }; Biarkan NumberOfGuesses = 0; const maxGuesses = 8; // Sekiranya tidak ada penyelesaian, tekaan kelegapan akan hampir 1, // Jadi kita boleh menggunakannya sebagai had atas untuk memeriksa keadaan tanpa penyelesaian. const opacityLimit = 0.99; // Gelung ini berulang kali menyempitkan tekaan kami sehingga kami mendapat hasilnya sementara (NumberOfGuesses <maxguesses numberofguesses const currentguess="opacityGuessRange.MidPoint;" kontras="getTextContrastWithimagePlusOverlay" overlaycolor imagepixelcolor: worldcontrastcolorinimage overlayopacity: isguesstoolow="Contress" isguesstoohigh="Contress"> DesiredContrast; jika (isGuessToolow) { opacityguessrange.lowerbound = currentGuess; } lain jika (isguesstoohigh) { opacityGuessRange.upperBound = currentGuess; } const newMidPoint = ((opacityguessrange.upperbound - opacityguessrange.lowerbound) / 2) opacityguessrange.lowerbound; opacityGuessRange.midpoint = newMidPoint; } const optimalOpacity = opacityguessrange.midpoint; const hasnosolution = optimalOpacity> opacityLimit; jika (hasnosolution) { console.log ('tiada penyelesaian'); // Mengendalikan situasi yang tidak dapat diselesaikan seperti yang diperlukan oleh OpacityLimit; } kembali optimum; }</maxguesses>
Sebaik sahaja percubaan selesai, kita sekarang tahu dengan tepat bagaimana telus yang perlu dibuat untuk membuat teks boleh dibaca tanpa menyembunyikan terlalu banyak imej latar belakang.
Kami melakukannya!
Penambahbaikan dan batasan
Kaedah yang kami perkenalkan hanya berkesan jika warna teks dan warna overlay sendiri mempunyai kontras yang mencukupi. Sebagai contoh, jika anda memilih warna teks yang sama seperti lapisan, tidak akan ada penyelesaian yang optimum kecuali imej tidak memerlukan lapisan sama sekali.
Juga, walaupun kontras boleh diterima secara matematik, ini tidak selalu menjamin ia kelihatan hebat. Ini terutama berlaku untuk teks gelap dengan lapisan cahaya dan imej latar belakang yang sibuk. Bahagian imej mungkin mengalihkan perhatian dari teks, dan mungkin sukar dibaca walaupun kontrasnya baik secara numerik. Itulah sebabnya nasihat popular adalah menggunakan teks cahaya pada latar belakang gelap.
Kami juga tidak menganggap kedudukan piksel atau bilangan piksel setiap warna. Satu kelemahan ini adalah bahawa piksel di sudut boleh mempunyai kesan yang berlebihan terhadap hasilnya. Tetapi manfaatnya ialah kita tidak perlu bimbang tentang bagaimana warna imej diedarkan atau di mana teks itu, kerana selagi kita berurusan dengan tempat -tempat yang paling kurang, kita boleh selamat di tempat lain.
Saya belajar sesuatu di sepanjang jalan
Selepas percubaan ini, saya telah memperoleh sesuatu dan saya ingin berkongsi dengan anda:
<code>- **明确目标非常有帮助!**我们从一个模糊的目标开始,即想要在图像上显示可读的文本,最终得到了一个我们可以努力达到的特定对比度级别。 - **明确术语非常重要。**例如,标准RGB并非我所期望的。我了解到,我认为的“常规”RGB(0到255)正式称为8位RGB。此外,我认为我研究的方程式中的“L”表示“亮度”,但它实际上表示“亮度”,这不能与“光度”混淆。澄清术语有助于我们编写代码以及讨论最终结果。 - **复杂并不意味着无法解决。**听起来很困难的问题可以分解成更小、更容易管理的部分。 - **当你走过这条路时,你会发现捷径。**对于白色文本在黑色透明叠加层上的常见情况,您永远不需要超过0.54的不透明度即可达到WCAG AA级可读性。 ### 总结…您现在有了一种方法可以在背景图像上使文本可读,而不会牺牲过多的图像。如果您已经读到这里,我希望我已经能够让您大致了解其工作原理。我最初开始这个项目是因为我看到(并制作了)太多网站横幅,其中文本在背景图像上难以阅读,或者背景图像被叠加层过度遮挡。我想做些什么,我想给其他人提供一种同样的方法。我写这篇文章是为了希望你们能够更好地理解网络上的可读性。我希望你们也学习了一些很酷的canvas技巧。如果您在可读性或canvas方面做了一些有趣的事情,我很乐意在评论中听到您的想法!</code>
Atas ialah kandungan terperinci Memaku kontras yang sempurna antara teks cahaya dan imej latar belakang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Sekiranya anda baru -baru ini mula bekerja dengan GraphQL, atau mengkaji semula kebaikan dan keburukannya, anda tidak akan ragu -ragu mendengar perkara seperti "Graphql tidak menyokong caching" atau

API Peralihan Svelte menyediakan cara untuk menghidupkan komponen apabila mereka memasuki atau meninggalkan dokumen, termasuk peralihan svelte adat.

Berapa banyak masa yang anda habiskan untuk merancang persembahan kandungan untuk laman web anda? Semasa anda menulis catatan blog baru atau membuat halaman baru, adakah anda memikirkan

Dengan pendakian harga bitcoin baru -baru ini lebih dari 20k $ USD, dan baru -baru ini melanggar 30k, saya fikir ia patut mengambil menyelam yang mendalam kembali ke dalam mewujudkan Ethereum

Perintah NPM menjalankan pelbagai tugas untuk anda, sama ada sebagai satu-satunya atau proses berjalan terus untuk perkara seperti memulakan pelayan atau menyusun kod.

Artikel ini membincangkan menggunakan CSS untuk kesan teks seperti bayang -bayang dan kecerunan, mengoptimumkannya untuk prestasi, dan meningkatkan pengalaman pengguna. Ia juga menyenaraikan sumber untuk pemula. (159 aksara)

Tidak kira tahap tahap anda sebagai pemaju, tugas yang kami selesaikan -sama ada besar atau kecil -membuat kesan besar dalam pertumbuhan peribadi dan profesional kami.

Saya hanya berbual dengan Eric Meyer pada hari yang lain dan saya teringat cerita Eric Meyer dari tahun -tahun pembentukan saya. Saya menulis catatan blog mengenai kekhususan CSS, dan
