實戰!半小時寫一個腦力小遊戲


本實戰使用了HTML5,CSS3和JavaScript的基本的技術。 咱們將討論數據屬性、定位、透視、轉換、flexbox、事件處理、超時和三元組。 你不須要在編程方面有太多的知識和經驗就能看懂,不過仍是須要知道HTML,CSS和JS都是什麼。css

  • 🕹Demo: Memory Game Project【https://marina-ferreira.github.io/memory-game/】(點擊底部「原文」直達GayHub項目)git

項目結構

先在終端中建立項目文件:es6

HTML

初始化頁面模版並連接 css文件 js文件.github

這個遊戲有 12 張卡片。 每張卡片中都包含一個名爲 .memory-card的容器 div,它包含兩個img元素。 一個表明卡片的正面 front-face,另外一個個表明背面 back-face編程


您能夠在GitHub下載本項目的資源文件: Memory Game Repo【https://github.com/code-sketch/memory-game】。bash

這組卡片將被包裝在一個 section容器元素中。 最終代碼以下:函數

CSS

咱們將使用一個簡單但很是有用的配置,把它應用於全部項目:性能

box-sizing: border-box屬性能使元素充滿整個邊框,因此咱們就能夠不用作一些數學計算了。flex

display:flex設置給 body,而且把 margin:auto應用到到 .memory-game容器,這樣可使它將垂直水平居中。this

.memory-game是一個彈性容器,在默認狀況下,裏面的元素會縮小寬度來適應這個容器。經過把 flex-wrap的值設置爲 wrap,會根據彈性元素的大小進行自適應。

每一個卡片的 widthheight都是用 CSS 的 calc()函數進行計算的。 下面咱們須要製做一個三行四列的界面,而且把 width設置爲 25%height設置爲 33.333%,還要再減去 10px留足邊距.

爲了定位 .memory-card子元素,還要添加屬性 position: relative,這樣咱們就能夠相對它進行子元素的絕對定位。

front-faceand back-faceposition屬性都設置爲 absolute,這樣就能夠從原始位置移除元素,並使它們堆疊在一塊兒。

這時頁面模版看上去應該是這樣:

咱們還須要添加一個點擊效果。 每次元素被點擊時都會觸發 :active僞類,它引起一個 0.2秒的過渡:

翻轉卡片

要在單擊時翻轉卡片,須要把一個 flip類添加到元素。 爲此,讓咱們用 document.querySelectorAll選擇全部 memory-card元素,而後使用 forEach遍歷它們並附加一個事件監聽器。 每當卡片被點擊時,都會觸發 flipCard函數,其中 this表明被單擊的卡片。 該函數訪問元素的 classList並切換到 flip類:

CSS 中的 flip類會把卡片旋轉 180deg

爲了產生3D翻轉效果,還須要將 perspective屬性添加到 .memory-game。 這個屬性用來設置對象與用戶在 z軸上的距離。 值越小,透視效果越強。 爲了能達得最佳的效果,把它設置爲 1000px

接下來對 .memory-card元素添加 transform-style:preserve-3d屬性,這樣就把卡片置於在父節點中建立的3D空間中,而不是將其平鋪在 z = 0的平面上(transform-style)。

再把 transition屬性的值設置爲 transform就能夠生成動態效果了:

耶!如今咱們獲得了帶有 3D 翻轉效果的卡片, 不過爲何卡片的另外一面沒有出現? 因爲絕對定位的緣由,如今 .front-face.back-face都堆疊在了一塊兒。 每一個元素的 back face都是它 front face的鏡像。 屬性 backface-visibility默認爲 visible,所以當咱們翻轉卡片時,獲得的是背面的 JS 徽章。

爲了顯示它背面的圖像,讓咱們在 .front-face.back-face中添加 backface-visibility:hidden

若是咱們刷新頁面並翻轉一張卡片,它就消失了!

img

因爲咱們將兩個圖像都藏在了背面,因此另外一面沒有任何東西。 因此接下來須要再把 .front-face翻轉180度:

效果終於出來了!

匹配卡片

完成翻轉卡片的功能以後,接下來處理匹配的邏輯。

當點擊第一張卡片時,須要等待另外一張被翻轉。 變量 hasFlippedCardflippedCard用來管理翻轉狀態。 若是沒有卡片翻轉,hasFlippedCard的值爲 trueflippedCard被設置爲點擊的卡片。 讓咱們切換到 toggle方法:

如今,當用戶點擊第二張牌時,代碼會進入 else塊,咱們將檢查它們是否匹配。爲了作到這一點,須要可以識別每一張卡片。

每當咱們想要向HTML元素添加額外信息時,就可使用數據屬性。 經過使用如下語法: data-*,這裏的*能夠是任何單詞,它將被插入到元素的 dataset 屬性中。 因此接下來爲每張卡片添加一個 data-framework

複製代碼


這下就能夠經過訪問兩個卡片的數據集來檢查匹配了。 下面將匹配邏輯提取到它本身的方法 checkForMatch(),並將 hasFlippedCard設置爲 false。 若是匹配的話,則調用 disableCards()並分離兩個卡上的事件偵聽器,以防止再次翻轉。 不然 unflipCards()會將兩張卡都恢復成超過 1500 毫秒的超時,從而刪除 .flip類:

把代碼組合起來:

更優雅的進行條件匹配的方法是用三元運算符,它由三部分組成: 第一部分是要判斷的條件, 若是條件符合就執行第二部分的代碼,不然執行第三部分:

鎖定

如今已經完成了匹配邏輯,接着爲了不同時轉動兩組卡片,還須要鎖定它們,不然翻轉將會被失敗。

先聲明一個 lockBoard變量。 當玩家點擊第二張牌時,lockBoard將設置爲true,條件 if (lockBoard) return;在卡被隱藏或匹配以前會阻止其餘卡片翻轉:

點擊同一個卡片

仍然是玩家能夠在同一張卡上點擊兩次的狀況。 若是匹配條件判斷爲 true,從該卡上刪除事件偵聽器。

爲了防止這種狀況,須要檢查當前點擊的卡片是否等於firstCard,若是是確定的則返回。

變量 firstCardsecondCard須要在每一輪以後被重置,因此讓咱們將它提取到一個新方法 resetBoard()中, 再其中寫上 hasFlippedCard = false;lockBoard = false。 es6 的解構賦值功能 [var1, var2] = ['value1', 'value2']容許咱們把代碼寫得超短:

接着調用新方法 disableCards()unflipCards()

洗牌

咱們的遊戲看起來至關不錯,可是若是不能洗牌就沒有樂趣,因此如今處理這個功能。

display: flex在容器上被聲明時,flex-items會按照組和源的順序進行排序。 每一個組由order屬性定義,該屬性包含正整數或負整數。 默認狀況下,每一個 flex-item都將其 order屬性設置爲 0,這意味着它們都屬於同一個組,並將按源的順序排列。 若是有多個組,則首先按組升序順序排列。

遊戲中有12張牌,所以咱們將迭代它們,生成 0 到 12 之間的隨機數並將其分配給 flex-item order屬性:

爲了調用 shuffle函數,讓它成爲一個當即調用函數表達式(IIFE),這意味着它將在聲明後當即執行。 腳本應以下所示:

終於完成了!

您還能夠在油管上找到視頻演示:🎬 Code Sketch Channel【https://www.youtube.com/watch?v=eMhiMsEC9Uk&list=PLLX1I3KXZ-YH-woTgiCfONMya39-Ty8qw】。


本文首發於京程一燈公衆號!!!

㊗️開工大吉

相關文章
相關標籤/搜索