<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0" > <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } .title { width: 512px; display: flex; align-items: center; justify-content: space-between; margin: 10px auto; } html { --wh: 256px; } .container { width: 512px; height: 512px; margin: 0 auto 0; background-color: #eee; user-select: none; } @keyframes hide { 0% { opacity: 1; } 100% { opacity: 0; } } .card { position: relative; width: var(--wh); height: var(--wh); transform-style: preserve-3d; transition: all .2s; float: left; border: 1px solid #000; &.rotate { transform: rotateY(180deg); } &.hide { animation: hide 1s forwards; } .front { position: absolute; top: 0; left: 0; z-index: 1; width: 100%; height: 100%; transform: translateZ(1px); background-color: pink; } .after { position: absolute; top: 0; left: 0; z-index: 0; width: 100%; height: 100%; transform: translateZ(-1px) rotateY(180deg); background-color: yellow; display: flex; align-items: center; justify-content: center; font-size: calc(var(--wh) / 2) } } </style> </head> <body> <div class="title"> <div class="fs">分數: 0</div> <div class="timeout">剩餘時間: 180秒</div> <button class="restart" onclick="restart()" >重新開始</button> </div> <div class="container"> <div class="card rotate"> <div class="front"></div> <div class="after">1</div> </div> </div> <script> const container = document.querySelector('.container'); const fsEl = document.querySelector('.fs') const timeout = document.querySelector('.timeout') let wh = 256 let fs = 0 let isHandle = false let time = 180 let timer = null function setTimer() { timer & clearInterval(timer) timer = setInterval(() => { time-- timeout.innerHTML = `剩餘時間: ${time}秒` if (time <= 0) { clearInterval(timer) alert(`時間到!您的得分為${fs}`) restart() } }, 1000) } function fsAdd() { fsEl.textContent = `分數: ${fs}` } function render() { document.documentElement.style.setProperty('--wh', `${wh}px`) const num = (512 / wh) ** 2 const temp = Array.from({ length: num / 2 }, (_, i) => i + 1) const list = [...temp, ...temp] const textContent = () => { const renderIndex = Math.floor(Math.random() * list.length) const val = list[renderIndex] list.splice(renderIndex, 1) return val } const els = document.createDocumentFragment() for (let i = 0; i < num; i++) { const card = document.createElement('div') card.classList.add('card') const front = document.createElement('div') front.classList.add('front') const after = document.createElement('div') after.classList.add('after') after.textContent = textContent() card.appendChild(front) card.appendChild(after) els.appendChild(card) } container.innerHTML = '' container.appendChild(els) addEvent() } render() function addEvent() { let boxs = document.querySelectorAll('.card') boxs.forEach(box => { box.addEventListener('click', () => { if (isHandle) return if (box.innerHTML === '') return isHandle = true box.classList.toggle('rotate') setTimeout(() => { checkIsDoublet() }, 300) }) }) setTimer() } function checkIsDoublet() { const boxs = document.querySelectorAll('.card.rotate') if (boxs.length === 2) { const first = boxs[0].querySelector('.after').textContent const second = boxs[1].querySelector('.after').textContent if (first === second) { console.log('===') boxs[0].classList.add('hide') boxs[1].classList.add('hide') fs += 1 fsAdd() setTimeout(() => { boxs[0].innerHTML = '' boxs[1].innerHTML = '' boxs[0].classList.remove('rotate') boxs[1].classList.remove('rotate') checkIsAllClear() }, 300) } else { boxs[0].classList.remove('rotate') boxs[1].classList.remove('rotate') isHandle = false } } else { isHandle = false } } function checkIsAllClear() { const fronts = document.querySelectorAll('.card .front') console.log(fronts, 'fronts') if (!fronts.length) { console.log('重新渲染') timeout.innerHTML = `剩餘時間: 180秒` wh /= 2 container.innerHTML = '' timer & clearInterval(timer) time = 180 render() } isHandle = false } function restart() { wh = 256 fs = 0 time = 180 timer & clearInterval(timer) render() } </script> </body> </html>