http://sandbox.runjs.cn/show/4r8uscsv
浏览器兼容性:
桌面:Latest Chrome (测试版本 40), Latest Firefox (测试版本 35), Latest Safari (测试版本 8)
不兼容IE (测试版本 11,谁知道它尼玛出了什么鬼问题)
手机:Latest Chrome (测试版本 39 on Android)
Sass
@font-face { font-family: "digital"; src: url(DIGITALDREAMSKEWNARROW-webfont.woff); } body { position: fixed; left: 0; right: 0; top: 0; bottom: 0; width: 400px; margin: auto; display: -webkit-flex; display: flex; -webkit-flex-direction: column; flex-direction: column; box-sizing: border-box; padding: 10px 0 5px; @media (max-width: 400px) { width: 100%; padding: 5px 0 0; } header { font-size: 50px; font-family: digital, monospace; height: 50px; text-align: center; line-height: 50px; } &.success header { color: green; } &.fail header { color: red; } main { -webkit-flex: 1; flex: 1; position: relative; overflow-y: hidden; border: 1px solid; box-sizing: border-box; margin-top: 5px; div::before { text-align: center; font: 40px monospace; display: block; height: 40px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; pointer-events: none; } & > div.row { height: 25%; display: -webkit-flex; display: flex; -webkit-flex-direction: row; flex-direction: row; position: absolute; top: 0; width: 100%; will-change: transform; transition: .05s all; box-sizing: border-box; & > div.column { height: 100%; width: 25%; -webkit-flex: 1; flex: 1; border: 1px solid; box-sizing: border-box; position: relative; transition: background .05s; &.error { background: red; } &.ok { background: green; } } @for $row from 0 through 5 { &[data-row="#{$row}"] { -webkit-transform: translateY(($row - 1) * 100%); transform: translateY(($row - 1) * 100%); } } &[data-row="0"] { transition: none; } @for $idx from 1 through 4 { &[data-next="#{$idx}"] { & > div:nth-child(#{$idx}) { background: black; color: white; } &::before { content: attr(data-count); left: 25% * ($idx - 1); right: 25% * (4 - $idx); color: white; z-index: 1; } } } &[data-row="4"], &[data-row="5"] { @for $idx from 1 through 4 { &[data-next="#{$idx}"] > div:nth-child(#{$idx}) { background: lightgray; } } &:not([data-next]) { background: yellow; & > div:nth-child(1)::before { content: "J"; } & > div:nth-child(2)::before { content: "K"; } & > div:nth-child(3)::before { content: "L"; } & > div:nth-child(4)::before { content: ";"; } } } } } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> <title>Don't Tap The White Block</title> </head> <body> <header><span id="time_span">0.000</span>"</header> <main> <div class="row" data-row="0" data-count="4"> <div class="column"></div> <div class="column"></div> <div class="column"></div> <div class="column"></div> </div> <div class="row" data-row="1" data-count="3"> <div class="column"></div> <div class="column"></div> <div class="column"></div> <div class="column"></div> </div> <div class="row" data-row="2" data-count="2"> <div class="column"></div> <div class="column"></div> <div class="column"></div> <div class="column"></div> </div> <div class="row" data-row="3" data-count="1"> <div class="column"></div> <div class="column"></div> <div class="column"></div> <div class="column"></div> </div> <div class="row" data-row="4"> <div class="column"></div> <div class="column"></div> <div class="column"></div> <div class="column"></div> </div> <div class="row" data-row="5"> <div class="column"></div> <div class="column"></div> <div class="column"></div> <div class="column"></div> </div> </main> </body> </html>
var rows = Array.prototype.slice.call(document.querySelectorAll("div.row")), timeSpan = document.getElementById("time_span"), startTime, showTimeHandle, count = 0; function randInt(max) { // [0, max) return (Math.random() * max) | 0; } (function() { for (var i=0; i<4; ++i) { rows[i].dataset.next = randInt(4) + 1; } })(); function showTime(t) { startTime = startTime || t; timeSpan.textContent = (((t - startTime) | 0) / 1000).toFixed(3); showTimeHandle = window.requestAnimationFrame(showTime); } function gameOver(isSucceed) { window.cancelAnimationFrame(showTimeHandle); showTimeHandle = null; document.body.classList.add("over"); document.body.classList.add(isSucceed ? "success" : "fail"); } function columnClicked(column) { if (document.body.classList.contains("success") || document.body.classList.contains("fail")) { return true; } if (startTime === undefined) { showTimeHandle = window.requestAnimationFrame(showTime); } var rowNext = rows.filter(function (row) { return Number(row.dataset.row) === 3; })[0]; if (Number(rowNext.dataset.next) !== column) { rowNext.children[column - 1].classList.add("error"); gameOver(false); return; } ++count; rows.forEach(function (row) { var rowNum = Number(row.dataset.row); if (rowNum === 5) { row.dataset.row = 0; row.dataset.count = count + 4; if (count >= 47) { delete row.dataset.next } else { row.dataset.next = randInt(4) + 1; } } else { row.dataset.row = rowNum + 1; } }); if (count === 50) { gameOver(true); } } document.querySelector("main").addEventListener("touchstart", function (e) { var touch = e.changedTouches[0]; var elem = document.elementFromPoint(touch.pageX, touch.pageY); if (elem.tagName == "DIV" && elem.classList.contains("column")) { var row = Number(elem.parentElement.dataset.row); if (row >= 2 && row <= 4) { var column = 1; while (elem = elem.previousElementSibling) { ++column; } columnClicked(column); } } }); window.addEventListener("keypress", function (e) { var column; switch (e.charCode) { case 106: column = 1; break; // J case 107: column = 2; break; // K case 108: column = 3; break; // L case 59: column = 4; break; // ; default: return; } columnClicked(column); });