我喜歡讓CSS做一些事情。這是您將在Minecraft建造計算器的解決問題的大腦訓練的類型,除非您可能不會找到與Minecraft Redstone一起工作的工作,而無論您獲得了多麼出色的工作,而CSS技能值得真正的錢,許多通才的程序員也害怕CSS,因此研究這可能是從包裝中脫穎而出的方式。另外,當您使用CSS完成不可能的情況時,所有正常的CSS任務似乎都很容易。
我在網絡上閱讀了有關CSS是否是Turing完整語言以及CSS和HTML是否符合編程語言的有趣討論。我還沒有決定,但是我可以說,在以標準方式支持常見的UI模式時,一些較新的CSS功能模糊了樣式和功能之間的界限。
挑戰自己僅使用CSS和HTML解決邏輯問題,可以迫使我們與CSS的一些新穎的,類似於CSS(例如自定義屬性和邏輯功能)共度美好時光。目前尚不清楚如何僅使用CSS來構建Sudoku求解器,但是儘管想法聽起來很瘋狂,但基於約束的Sudoku邏輯似乎可能與CSS的聲明性質兼容,因此我並沒有震驚地發現其他人聲稱自己構建了“ CSSS3 Sudoku soloku soliver lover”。事實證明,這更像是CSS中的Sudoku驗證器,而不是求解器。它還使用了一小撮JavaScript來使用文本框。
經過數天的英勇試圖在純CSS中構建一個完整的Sudoku求解器和發電機應用程序後,我學到了三件事。
但是,我們可以實現16平方公的sudoku求解器和生成器應用程序,您可以在下面播放,然後我們將分解其功能的工作方式。您的上帝現在在哪裡,旨在給幼兒的簡單難題?
由於我們正在嘗試CSS,因此我們在合同上有義務包括視覺上有趣的內容,儘管沒有什麼太過分了,因為Sudoku播放器似乎欣賞了一個UI,而UI則持續不斷。在我看來,您在一些Sudoku應用程序上選擇數字的方式可能更直觀,因此我決定應用Radial菜單UI模式,該模式的歷史可以追溯到Black and White Macintosh的日子,並且在現代視頻遊戲中仍然很受歡迎。實際上,有人為徑向菜單構建了一個不錯的純CSS庫,但是我喜歡React Planet,因為我喜歡它捕獲其既有與周圍圓圈的項目的方式,又如何吸引人的動作。我想看看我是否只能使用CSS構建類似的效果。
我從這支筆中拿出了一些虛線的圓形代碼,然後使用舊的Border-Radius:50%的技巧從標籤中刪除了數字,然後我使用絕對定位將數字“粘貼”到虛線圓上的正確點,即使動畫使其更改大小。
.context .number.top { 背景:綠色; 左翼:自動; 邊緣權利:自動; 左:0; 右:0; 頂部:-12.5px; } .context .number.left { 背景:橙色; 保證金頂:自動; 保證金底:自動; 頂部:0; 底部:0; 左:-12.5px; }
動畫在使其z索引更高時逐漸消失,因此可以單擊。我們還將頂部和左邊的餘量從50%到零動畫,因此圓圈從中心擴展以填充可用的空間。
@keyframes彈跳{ 0%{ z index:-1; 寬度:35%; 身高:35%; 左鍵:50%; 保證金頂:50%; 不透明度:0; } 100%{ z索引:2; 不透明度:1; 寬度:var(-Circle-radius); 高度:var(-Circle-radius); } }
然後,為了模擬類似於React Planet的彈性物理學,我在動畫上使用Cux-Bezier()函數。網站Easings.net對使寬鬆功能變得容易。
.情境 { 動畫:彈跳立方體bezier(.68,-0.6,.32,2.5).5s前鋒; }
選擇值選擇的值的選擇和使用無線電按鈕hacks操作的值選擇器的行為,以記住選擇了哪些值並實現相互的排他性。 CSS-Tricks在復選框和無線電按鈕hacks上有一篇出色的文章,因此我不會在此處重複此信息,但是我將根據複選框將CSS變量設置在Sudoku CSS網格級別上,因為這對於該實驗的工作方式至關重要。
當我們使用變量時,我們可以在設置值時獲得相同的行為,而不管是用戶檢查框以指定值還是拼圖發生器為正方形設置相同的值。正方形和值的組合很多,因此我們使用Sass,而不是手工編寫所有組合。我們還為每個值平方組合創建單獨的位值,以及另一個自定義屬性,以告訴我們該廣場是否未解決。這是因為CSS使我們有限地將一個值與另一個值進行比較的能力有限(這是可能的,但可能很棘手)。我們正在以一開始可能看起來有些奇怪的方式定義這些價值,但是在驗證一組Sudoku Square值是否可以解決時,我們的生活更加輕鬆。
@for $ i從1到16 { @for $ j從1到4 { #select-#{$ j} -value-square-#{$ i}:檢查〜.sudoku { - 平方 - #{$ i} -unsolved:0; - -Square-#{$ i} -equals - #{$ j}:1; } } }
Google醫生告訴我們,即使只有16個正方形,也有四個數字的40億可能組合。但是,一個程序迫使所有這些組合併輸出根據Sudoku規則有效的程序表明,在4×4 Sudoku中只有288個有效解決方案,這與9×9網格中可能的有效解決方案的數量很大。只有288種可能的解決方案,這就是Sass真正可以自己進入的地方。我仍然不確定CSS是否是Turing完整的語言,但是Sass是,它為我們提供了一些適當的數據結構,例如列表。有了一點正則魔術,我們可以將上面鏈接的有效4×4難題的列表轉換為牢固的二維列表!
$解決方案:((1,2,3,4,3,4,1,2,2,4,4,3,4,3,2,1),(3,1,2,4,2,4,2,4,1,3,3,3,4,2,4,2,4,2,3,3,3,3,3,3,3,3,3,3,1)(1,2,3,3,3,3,4,4,4,4,2,2,22, 222.2,222.2,222.2,222,222,222,222,222,2後來...*/(2,4,3,1,3,1,4,4,2,4,2,1,3,1,3,2,4),(4,3,2,2,1,2,2,1,4,4,3,3,3,3,4,1,2,2,2,3,3,4));
甜的!如果我們的CSS黑客是多層應用程序,這將是我們的數據庫。驗證可以使用相同的方法檢查行和列值,例如我們在簡介中看到的9×9驗證器,但是由於我們知道答案似乎不需要打擾檢查塊,列和行。相反,我們可以檢查輸入的數字是否仍然是一個有效的難題。在偽代碼中,這可能看起來像:
foreach(正方形) { if(solutionsContains(S.Value,S.Index)或s.isunsolved()) { ShowValidationError(); } }
還記得我們每當選擇平方值時就創建了這些怪異的變量嗎?
- 平方 - #{$ i} -unsolved:0; - -Square-#{$ i} -equals - #{$ j}:1;
因此,現在我們在上述偽代碼的第3行中有兩個問題的答案,但是我們如何在CSS中執行邏輯或操作員?關於CSS-Tricks有一篇很棒的文章,內容涉及使用Calc()模擬CSS中的邏輯運算符,而且我不確定沒有它的情況下我會想到我的Sudoku Solver中的某些代碼,但是該文章中解釋的某些公式會變得有些笨拙,尤其是如果您想與更多的ands and and ands and ands ands ands ands ands ands ands和Ors一起使用。例如,我們需要該偽代碼的CSS等效物:
if(((squareOneEqualsOne和squaretwoequalstwo /*....*/以及squaresixteenequalsone)或(squareOneEqualsOne和squaretwoequalsone / equarequalsthree / he...* / and squaresixteenEqualsone))) { sudokuisvalid(); } }
好吧,這篇文章顯示了2019年使用calc()編寫瞭如何使用calc()進行邏輯。除了calc()之外,我們還擁有良好支持的min()和max()數學功能,可以更好地滿足我們的需求。如果您Google google“ CSS Min,Max和夾具”(最後一個只是方便的糖,即Min()和Max()),您會發現許多示例顯示瞭如何使用它們來簡化流體排版。這是一種引人注目的用例,但是您可以在使用數字的任何地方使用這些數學功能,這為CSS增加了很多功能。例如,如果將位標誌變量傳遞給CSS Min(),則相當於和。如果將相同的標誌傳遞給CSS Max(),則相當於OR。我們可以使用以下真相表證明這一點。
我們可以對此非常複雜,尤其是當您添加有用的事實,即我們可以在min()和max()內完成任何calc()可以做的事情。 CSS剛剛邁出了自己的怪異腳本語言。現在,我們可以在CSS中的驗證偽代碼中實現條件。 (實際上,我們從Sass產生了這一點,因為它非常重複。)
.sudoku { -square-1匹配式puzzle-1:max(var(-square-1-------------------- square-1-equals-1,0)); -square-2匹配式puzzle-1:max(var(-square-2-無分解),var(-square-2- equals-2,0)); /*....*/ --square-16匹配式puzzle-1:max(var(-square-16---隔離),var(-square-16-equals-1,0)); - puzzle-1-found:min(-var(-square-1匹配式Puzzle-1), /*....*/ var(-square-16匹配式puzzle-1)); - 解決方案:max(-var(-puzzle-1-found),//...* / var(-puzzle-puzzle-288-found)); }
通過檢查每個正方形是否尚未解決或具有從SASS 2D列表中的一個預計算解決方案中存在相同位置的值,我們可以產生一個變量,告訴我們當前定義的正方形是否存在於有效的4×4 Sudoku拼圖中。現在,只要我們能找到可以在CSS中推動行為的數字,我們就可以基於CSS行為 - 解決方案。例如,為了使我們的網格無效時將其變成紅色,我們可以將其放在每個正方形中:
。正方形 { 顏色:rgb(calc(255 *(1-var( - solution-found))),0,0); }
並非每個CSS屬性都可以由一個數字驅動,但是許多可以驅動,而z索引和不透明度尤其是此用法的通用CSS屬性。其他行為可能更棘手,但通常可以實現。例如,我想如何觸發僅使用數字標誌屬性觸發無效網格的搖動動畫的問題,以便網格將搖動任何時間變得無效,但這是一個很好的例子,說明了黑客攻擊CSS如何強迫您閱讀規格並了解每個屬性的邊緣案例。我在此頁面上找到了有關動畫效果的解決方案。
默認值0s的值表示不應發生動畫。
因此,我們可以將動畫動畫的動畫持續時間基礎 - 解決方案 - 每次使用以下數字單擊一個數字時,請刪除動畫,每當解決方案變得無效時,動畫級都可以使動畫重播,否則什麼也不做。
#select-#{$ j} -value -Square-#{$ i}:active { 動畫:無; } #select-#{$ j} -value-square-#{$ i}:檢查〜.sudoku { 動畫:Shake Cupic-Bezier(.36,.07,.19,.97)calc((夾具(0,1-1-var( - solution-found),1),1)) * 1s) * 1s); }
如果我們沒有CSS自定義屬性,那麼純CSS Sudoku應用程序可能是不可能的,並且它們乍一看更強大。每當屬性依賴更改的屬性時,它們都會重新評估並更新UI,就像您從vue之類的精美JavaScript框架中獲得的反應性的更簡單版本。公平地說,反應性是以CSS變量的形式構建到瀏覽器中的!
現在,我們已經有了這種驗證方法,並且我們的樣式表知道在我們在sudoku中設置有效值時,我們就會在其潛意識中的解決方案,我們接近實施求解器!
還記得當我們引入這些中間變量時嗎?
.sudoku { - puzzle-1-found:min(-var(-square-1匹配式Puzzle-1), /*....*/ var(-square-16匹配式puzzle-1)); }
這不僅是為了使驗證代碼更容易編寫和理解。知道288個可能的拼圖中的哪個是匹配的,這使我們能夠編寫求解器!
#no-solution { z索引:1; 顏色:紅色; } @for $ solution-index從1到288 { label [for = solution-#{$ solide-index}] { 光標:指針; z-index:calc(var( - puzzle-#{$ solide-index} -found) *#{$ solution-index}); } #solution-#{$ solide-index}:檢查〜.sudoku { @for $ square從1到16 { - 平方 - #{$ square} -solution:“#{nth(nth($ solutions,$ solutions-index),$ square),$ square)}”; - 平方 - #{$ square} - 彩色:灰色; -auto-#{$ square}:1; }
我將可選的複數放在上面的“拼圖”一詞中,因為如果用戶沒有填寫許多正方形,則可能有多種有效的解決方案。我挖掘像這樣的javaScript的求解器,即使您沒有指定足夠的值以使人類能夠在不猜測的情況下解決該解決方案。
我的CSS求解器中的訣竅是,雖然“求解”按鈕看起來像一個按鈕,但實際上是288個廣播按鈕標籤將一個堆疊在另一個按鈕上,但所有人看起來都一樣。想像一下一堆卡片:它們的背面都具有相同的設計,但前面的值不同。求解器邏輯將解決方案放在堆堆的頂部,並帶有z索引,因此,如果您拿起它並讀取其另一側,您將始終具有正確的解決方案。如果有多個正確的解決方案,它仍然有效,因為我們以後在我們的有效答案列表中出現的解決方案將放在頂部,因為我們通過將標誌乘以$ solution-index來計算z索引。如果不匹配解決方案,則所有求解按鈕的z索引將為零,並且由於帶有“無效拼圖”消息的按鈕的禁用版本具有一個Z索引,因此它將出現在頂部。如果拼圖第一是解決方案,我們仍然會看到一個拼圖一個按鈕,因為無效的按鈕在HTML中較早出現。
如果您還沒有閱讀,那麼堆疊上下文可能會出乎意料的行為,因此這是一種不太明顯的堆疊行為的很好的例證。
我們可以將生成難題視為具有額外要求的求解器的另一個版本。
CSS沒有隨機()函數(儘管SASS確實可以),因此每次按下同一按鈕時,我們如何獲得不同的行為可能並不明顯。但是上面的求解器解釋有點像擾流板,因為它已經在看起來像單個元素的按鈕上做的類似的操作,但實際上取決於當前有效的解決方案。
“生成”按鈕的問題是,每次點擊時,我們如何獲得不可預測的結果。全部歸功於Alvaro Montoro在有關如何使用CSS產生看似隨機價值的CSS漫步的文章。無線電按鈕hacks和動畫堆疊順序的組合似乎很好地奏效了。我努力看我是否可以在沒有額外加價的情況下做到這一點,但是我得出結論,這種方法是最好的,最簡單的。為了重複使用求解器解釋的卡片類比,這就像拼圖卡的甲板一直在不景氣,因此每當您拿起卡時,都會發現它的面孔不同。
我們可以將此偽隨機性與Sass Random()函數提供的實際隨機性結合在一起,以使我們的Sudoku遊戲重播值。
@for $ j從0到287 { 標籤[for = generate#{$ j}] { animation-delay:#{$ j * .35s}; } 標籤[for = generate#{$ j}]:active:After { z索引:300; 寬度:100%; } #generate#{$ j}:檢查〜.sudoku { $ blockcounts:(1:2,2:2,3:3:3,4:2); $ shufflesquares:(1,2,3,4,5,6,7,8,9,10,11,11,12,13,14,15,16); @for $ square從1到16 { $ index1:隨機(16); $ index2:隨機(16); $ temp:nth($ shufflesquares,$ index1); $ shufflesquares:set-nth($ shufflesquares,$ index1,nth($ shufflesquares,$ index2)); $ shufflesquares:set-nth($ shufflesquares,$ index2,$ temp); } @each $ square in $ shufflesquares { $ row:ceil($ square/4); $ linter:1($ square -1)%4; $ block:if($ row< 3,1,3)if($ column 0){ $ BLOCKCOUNTS:MAP -MERGE($ blockcounts,($ block:$ count -1)); - 平方 - #{$ square} -unsolved:0; - -Square-#{$ square} -equals - #{$ val}:1; @for $ ether-value從1到4 { @if($ elet-value!= $ val){ - 平方 - #{$ square} - equals - #{$ elet-elet-value}:0; } } - 平方 - #{$ square} - 彩色:灰色; -auto-#{$ square}:1; } } } }
對於每個“塊”(對於Sudoku說明了Sudoku說話的Sudoku網格,周圍有較厚的邊框),我們使用SASS隨機選擇四個正方形中的兩個來解決,除了一個“ gimme”正方形,只有一個未解決的正方形。由於驗證邏輯和求解器邏輯使用變量,而不是直接基於使用值選擇器檢查的值,因此驗證和求解邏輯的行為都相同。這意味著生成的值的處理方式與用戶單獨選擇每個值一樣。
這是在前11秒內勾選的計時器。
我們將在稍後進入CSS進行求解計時器,但是讓我們首先展示其中一位數字在沒有CSS溢出的情況下,將元素設置為隱藏,並在元素周圍有一個綠色邊框,以顯示動畫的每個步驟都可以向用戶看到的部分。
我們使用無限重複重複的密鑰幀動畫來以所需的間隔將可能的數字列表移到左側(我們使用單個字體,以便我們可以確保每個字符都佔據相同的寬度相同)。秒數將從零增加到九個,而下一個數字只能達到五個數字,每10秒增加一次,然後在兩個秒的兩個數字都需要重置為零之前。
每個數字都使用與CSS中的SpriteSheet動畫相同的技術進行動畫動畫,除非動畫不將圖像背景移動以實現動畫效果,我們正在移動包含可能數字的偽元素。
與CSS中的許多任務一樣,在CSS中製作動畫計數器有多種方法。但是,有些人不起作用跨瀏覽器,並且確實需要預處理程序來保持代碼簡潔。我喜歡我的方法,因為它很短。 CSS進行繁重的舉重,以弄清楚何時以及如何移動到下一個數字。標記所需要做的就是創建一個佔位持有人,每個數字都可以使用,為我們提供了一些介紹計時器的自由。
這是標記:
<div> <div> </div> <div>:</div> <div> </div> <div> </div> </div>
…和CSS:
.StopWatch { 文字平衡:中心; font-family:單域; 邊緣底:10px; } 。象徵 { 寬度:1ch; 溢出:隱藏; 顯示:inline-flex; 字體大小:5ch; } .symbol:nth-child(1):: after { 動畫:TENS 3600S步驟(6,End)無限; 內容:'012345'; } .symbol:nth-child(2):: after { 動畫:單位600s步驟(10,端)無限; 內容:'0123456789'; } .symbol:nth-child(4):: after { 動畫:60s步驟(6,端)無限; 內容:'012345'; } .symbol:nth-child(5):: after { 動畫:單位10s步驟(10,端)無限; 內容:'0123456789'; } @KeyFrames單位{ 到 { 變換:Translatex(-10CH); } } @KeyFrames Tens { 到 { 變換:Translatex(-6CH); } }
您可能會注意到,櫃檯從一個小時後從一開始就再次開始。那是因為所有迭代計數都設置為無限。我們可以修復它,但是我認為,如果有人花一個小時解決其中一個,那麼他們的問題比兒童的Sudoku難題更大。 ?
但是,不公平的是,即使用戶產生了新的難題,我們即使使用相同的計時器才能繼續滴答作響。我們可以重置嗎?事實證明,我們已經在本文的第一步中解決了這個問題,我們使用:Active pseudo-class刪除並有條件地重新添加了我們的數字選擇器的動畫。這次,這實際上更簡單,因為每次我們點擊“生成”按鈕時,我們都想刪除所有數字上的動畫,以將它們帶回零。然後,當無線電按鈕不再活動時,動畫將再次開始。因此,每次生成時,我們只需要重置計時器即可!
輸入[名稱=生成]:Active〜.StopWatch .Symbol :: after { 動畫:無; }
即使解決了難題,我也希望通過向玩家提供視覺反饋的時間性能來提供重播價值,並挑戰他們更快地解決難題。我還想通過為您提供簡約的循環規格來獎勵您在本文中的獎勵,您可以在自己的項目中重複使用。這是一支帶有圓形尺度的獨立筆,供您實驗:
我們正在應用遊戲中的勝利屏幕中使用的相同原理,除了在這支筆中,顯示的額定值由無線電按鈕hacks控制,而在遊戲中,它受動畫的控制,隨著時間的流逝,該動畫會慢慢移動到較低的評分。遊戲中的量規使用零不透明度隱藏,並且只有在我們發現拼圖已被手動解決時才顯示(並暫停)。
讓我們解釋一下我們如何創建半圓形的幻覺,該半圓被顏色分為兩側。實際上,它是一個完整的CSS圓圈,其下半部分使用溢出:隱藏。
我們使用偽元素應用兩種顏色,該元素填充了
然後,我們使用另一個裝有遊戲背景顏色的圓圈切成一個甜甜圈,以製作甜甜圈,然後使用Flexbox在更大圓圈內。
接下來,將其一半的容器的大小放置在整個圓圈的一半中,然後使用溢出:隱藏。
現在,如果我們旋轉甜甜圈,則量規似乎在充滿綠色或失去綠色,具體取決於我們是通過負還是正度旋轉甜甜圈!
我們想將標籤放在儀表的兩端,並在它們之間進行描述,事實證明,Flexbox是一個優雅的解決方案:
#rating { 字體大小:30px; 顯示:Flex; 寬度:300px; 正當:中間的空間; }
這是標記:
<div> <div>? </div> <div> </div> <div>? </div> </div>
這就是我們要定位標籤所需要的。如果額定值
至於控制描述所說的內容,它類似於我們用於計時器的技巧,除非這次我們在垂直方面而不是水平進行操作,因為反饋說明具有可變的長度。但是它們總是相同的高度。
我打開了這篇文章,疑問CSS是否是一種編程語言。很難說我們能夠僅使用CSS來實施的邏輯不是編程,但是至少可以說,其中一些是不尋常的用法。與科技界中的許多事情一樣,答案似乎是“取決於”,而且我們通過該實驗了解了CSS,我們還說明了編程與技術一樣重要。
沒有免責聲明,沒有CSS黑客文章是完整的,儘管我們已經證明我們可以在CSS中實現複雜的邏輯並在此過程中學習很多東西,但大多數情況下,我們可能不應該在生產中做到這一點,因為可維護性,可訪問性和其他一些以“ eRisition”結尾的單詞。
但是我們還看到,有些事情(例如,我認為使用CSS變量獲得的內置反應性)在CSS中非常方便,但可能要求我們在JavaScript中經過籃球,並可能使用框架。通過突破CSS的限制,我們最終創建了一個圓形量規,我認為可以合理地使用該圓形量規,甚至與達到一些JavaScript小部件相比,甚至可能是正確的事情,這些小部件可能很重並且做得超出了我們的真正需要。
在我對CSS Sudoku應用程序的願望清單上是一個重置按鈕。當前,如果您想啟動新的Sudoku遊戲,則必須刷新頁面。這是無線電按鈕hacks的固有限制,這使得CSS的黑客與常規編程不同。在一個階段,我相信當我認為動畫可以用於設置CSS變量時,我發現了一個解決方案 - 但事實證明,這是CSS Houdini的一部分,並且僅在基於鉻的瀏覽器中支持。如果到處都得到支持時,它將打開Pandora的黑客盒子,並很有趣。在將來的文章中,我什至可以探討為什麼我們在Chrome中擁有的這一無害功能是CSS黑客的遊戲規則改變者。
陪審團仍在CSS中是否可以使用完整的81平方英尺的sudoku求解器,但是如果您很好奇,請在評論中留下反饋。如果有足夠的人想要它,我們可能會一起掉下那隻兔子的洞,看看在此過程中可以照亮的CSS的黑暗角落。
以上是在CSS中生成(和解決!)的詳細內容。更多資訊請關注PHP中文網其他相關文章!