HTML和CSS的強大功能總是令人驚嘆不已。 Popover API 的全新交互特性再次證明了僅使用這兩種語言就能實現的驚人效果。
您可能已經看過其他教程展示了Popover API 的功能,但這篇文章更側重於將其“徹底征服”。我們將添加一些額外的“趣味”元素,例如氣球……一些字面意義上的“爆破”效果。
我使用僅HTML和CSS(當然)創建了一個遊戲,並依賴於Popover API。您的任務是在一分鐘內盡可能多地戳破氣球。但要小心!有些氣球(正如咕嚕所說)是“狡猾的”,會觸發更多氣球。
我巧妙地將其命名為Pop(over) the Balloons,我們將一步一步地一起製作它。完成後,它看起來會像(好吧,完全像)這樣:
只要我們使用popover
屬性對其進行設計,任何元素都可以作為彈出框:
<div popover="">...</div>
我們甚至不需要為popover
提供值。默認情況下,popover
的初始值為auto
,並使用規範中所謂的“輕量級關閉”。這意味著可以通過點擊彈出框外部的任何位置來關閉彈出框。當彈出框打開時,除非它們嵌套在一起,否則頁面上的任何其他彈出框都會關閉。 auto
彈出框就是這樣相互依賴的。
另一個選項是將popover
設置為manual
值:
<div popover="manual">...</div>
這意味著元素是手動打開和關閉的——我們必須點擊一個特定的按鈕才能打開和關閉它。換句話說,manual
創建了一個頑固的彈出窗口,只有當您點擊正確的按鈕時才會關閉,並且完全獨立於頁面上的其他彈出窗口。
使用Popover API構建遊戲的挑戰之一是,您無法加載頁面時彈出框已經打開……如果我們的目標是僅使用HTML和CSS構建遊戲,則無法使用JavaScript解決這個問題。
這時就需要details
元素。與彈出框不同,details
元素可以默認打開:
<details open=""></details>
如果我們採用這種方法,我們就可以顯示一堆按鈕(氣球),並通過關閉<code><details></details>
來“戳破”所有氣球,直到最後一個氣球。換句話說,我們可以將起始氣球放在打開的<code><details></details>
元素中,以便在加載頁面時顯示它們。
這就是我所說的基本結構:
<details open=""><summary>?</summary>???</details>
這樣,我們可以點擊<summary></summary>
中的氣球來關閉<code><details></details>
並“戳破”所有按鈕氣球,留下一個氣球(最後的<summary></summary>
(稍後我們將解決如何移除它)。
您可能會認為<dialog></dialog>
對於我們的遊戲來說是一個更有語義的方向,您是對的。但是使用<dialog></dialog>
有兩個缺點,我們在這裡無法使用它:
<dialog></dialog>
的方法是使用JavaScript。據我所知,沒有我們可以添加到遊戲中來關閉頁面加載時打開的<dialog></dialog>
的關閉方法。 <dialog></dialog>
是模態的,並在打開時阻止點擊其他內容。我們需要允許玩家戳破<dialog></dialog>
之外的氣球才能擊敗計時器。 因此,我們將使用<details open=""></details>
元素作為遊戲的頂級容器,並使用普通的<div>作為彈出窗口本身,即<code><div popover="">。目前,我們只需要確保所有這些彈出框和按鈕都連接在一起,以便點擊按鈕打開彈出框。您可能已經從其他教程中學到了這一點,但是我們需要告訴彈出框元素它需要響應哪個按鈕,然後告訴按鈕它需要打開哪個彈出窗口。為此,我們為彈出框元素提供一個唯一的ID(所有ID都應該是),然後在按鈕上使用<code>popovertarget
屬性引用它:
<div popover="">...</div>
當所有內容都連接在一起時,這就是想法:
在最後一個演示中,還需要做一些工作。到目前為止,遊戲的一個缺點是,點擊彈出窗口的按鈕會打開更多彈出窗口;再次點擊同一個按鈕,它們就會消失。這使得遊戲過於簡單。
我們可以通過在按鈕上設置popovertargetaction
屬性(不,HTML規範作者並不關心簡潔性)來分離打開和關閉行為。如果我們將屬性值設置為show
或hide
,則按鈕將僅對該特定彈出框執行一項操作。
<div popover="manual">...</div>
請注意,我在<div>內添加了一個新的按鈕,該按鈕設置為目標另一個<code><div>,通過故意<em>不</em>在上面設置<code>popovertargetaction
屬性來打開或關閉。看看“戳破”元素是多麼具有挑戰性(以一種好的方式):
現在我們需要為<summary></summary>
和按鈕元素設置相同的樣式,以便玩家無法區分它們。請注意我說的是<summary></summary>
而不是<code><details></details>。這是因為<summary></summary>
是我們點擊打開和關閉<code><details></details>容器的實際元素。
大部分工作都是標準的CSS工作:設置背景、填充、邊距、大小、邊框等。但是有一些重要的事情,並非一定直觀,需要包含在內。
<summary></summary>
元素上將list-style-type
屬性設置為none
,以去除指示<code><details></details>是否打開或關閉的三角形標記。該標記非常有用,並且默認情況下非常好,但是對於這樣的遊戲,最好刪除該提示以獲得更好的挑戰。 summary::-webkit-details-marker
設置為display: none;
。 <summary></summary>
元素上設置cursor: pointer
。 <summary></summary>
上設置user-select
屬性為none
,以防止氣球(只是表情符號文本)被選中。這使它們更像頁面上的對象。 -webkit-user-select
屬性來考慮Safari支持。謝謝,蘋果。 將所有這些代碼放在我們將用於按鈕和<summary></summary>
元素的.balloon
類中:
<div popover="">...</div>
氣球的一個問題是,其中一些氣球是故意什麼也不做的。這是因為它們關閉的彈出框沒有打開。玩家可能會認為他們沒有點擊/點擊特定氣球或遊戲壞了,因此讓我們在氣球處於點擊的:active
狀態時添加一些縮放:
<div popover="manual">...</div>
獎勵:因為光標是一隻指向其食指的手,所以點擊氣球有點像手用手指戳氣球。 ???
我們在屏幕上分配氣球的方式是另一個需要考慮的重要因素。如果沒有JavaScript,我們就無法隨機放置它們,所以這是不可能的。我嘗試了很多方法,例如創建我自己的“隨機”數字,定義為可作為乘數使用的自定義屬性,但我無法在不重疊氣球或建立某種視覺模式的情況下獲得整體“隨機”效果。
我最終使用一個類來在不同的行和列中定位氣球的方法——不像CSS網格或多列,而是基於物理內插的虛構行和列。它看起來有點像網格,而且不像我想要的那樣“隨機”,但是只要沒有氣球具有相同的兩個類,它們就不會相互重疊。
我決定使用一個8×8的網格,但留空了第一“行”和“列”,這樣氣球就不會遮擋瀏覽器的左邊緣和上邊緣。
<details open=""></details>
我們已經準備好大部分遊戲組件,但是最好有一個勝利的彈出框來祝賀玩家在規定時間內成功戳破所有氣球。
一切都回到了<details open=""></details>
元素。一旦該元素未打開,遊戲就應該結束,最後一步是戳破最後一個氣球。因此,如果我們給該元素一個ID,例如#root
,我們可以創建一個條件,當它處於未打開狀態時使用display: none;
將其隱藏:
<div popover="">...</div>
在這裡,擁有:has()
偽選擇器非常棒,因為我們可以使用它來選擇#root
元素的父元素,以便當#root
關閉時,我們可以選擇該父元素的子元素——一個具有#congrats
ID的新元素——來顯示一個偽彈出框,向玩家顯示祝賀消息。 (是的,我知道這很諷刺。)
<div popover="manual">...</div>
如果我們在此時玩遊戲,我們可以在沒有戳破所有氣球的情況下收到勝利信息。同樣,手動彈出框不會關閉,除非點擊正確的按鈕——即使我們關閉其祖先<code><details></details>元素。
有沒有辦法在CSS中知道彈出框是否仍然打開?是的,輸入:popover-open
偽類。
:popover-open
偽類選擇一個打開的彈出框。我們可以將其與之前的:has()
結合使用,以防止在頁面上仍然打開彈出框時顯示消息。以下是將這些內容鏈接在一起以像and
條件語句一樣工作的方法。
<details open=""></details>
現在,只有當玩家真正獲勝時,才會收到祝賀。
相反,如果玩家無法在一分鐘計時器到期前戳破所有氣球,我們應該通知玩家遊戲結束。由於我們在CSS中沒有if()
條件語句(至少現在還沒有),我們將運行一分鐘的動畫,以便此消息淡入以結束遊戲。
<details open=""><summary>?</summary>???</details>
但是我們不希望失敗消息在勝利屏幕顯示時觸發,因此我們可以編寫一個選擇器來防止#fail
消息與#congrats
消息同時顯示。
<details open=""><summary>?</summary>?</details><div popover="manual"> <h2>Level 1 Popup</h2> </div>
玩家應該知道他們有多少時間戳破所有氣球。我們可以使用一個元素創建一個相當“簡單”的計時器,該元素佔據屏幕的全部寬度(100vw),在水平方向上縮放它,然後將其與上面的動畫匹配,該動畫允許#fail
消息淡入。
<details open=""><summary>?</summary>??</details><div popover="manual"> <h2>Level 1 Popup</h2>? </div>
只有一個失敗點可能會使遊戲過於簡單,因此讓我們嘗試添加第二個<code><details></details>元素,並使用第二個“root”ID,#root2
。同樣,我們可以使用:has
檢查#root
和#root2
元素是否都沒有打開,然後再顯示#congrats
消息。
.balloon { background-color: transparent; border: none; cursor: pointer; display: block; font-size: 4em; height: 1em; list-style-type: none; margin: 0; padding: 0; text-align: center; -webkit-user-select: none; /* Safari fallback */ user-select: none; width: 1em; }
剩下的唯一事情就是玩遊戲!
有趣,對吧?我確定我們可以在沒有自我強加的無JavaScript方法限制的情況下構建更強大的東西,而且我們並沒有認真對待可訪問性,但是將API推向極限既有趣又具有教育意義,對吧?
我很感興趣:您還能想到哪些古怪的想法來使用彈出框?也許您想到了另一個遊戲、一些漂亮的UI效果,或者一些巧妙的方法將彈出框與其他新興的CSS功能(如錨點定位)結合起來。無論是什麼,請分享!
以上是彈出氣球的詳細內容。更多資訊請關注PHP中文網其他相關文章!