panel with a timer, shuffle button
This commit is contained in:
parent
c01ac52bbd
commit
15dbe4487f
5
mj/.idea/.gitignore
generated
vendored
5
mj/.idea/.gitignore
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
6
mj/.idea/misc.xml
generated
6
mj/.idea/misc.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="JavaScriptSettings">
|
|
||||||
<option name="languageLevel" value="ES6" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
12
mj/.idea/mj.iml
generated
12
mj/.idea/mj.iml
generated
@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="WEB_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
8
mj/.idea/modules.xml
generated
8
mj/.idea/modules.xml
generated
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/mj.iml" filepath="$PROJECT_DIR$/.idea/mj.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
17
mj/icons/refresh.svg
Normal file
17
mj/icons/refresh.svg
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
|
||||||
|
<defs id="defs3051">
|
||||||
|
<style type="text/css" id="current-color-scheme">
|
||||||
|
.ColorScheme-Text {
|
||||||
|
color:#eff0f1;
|
||||||
|
}
|
||||||
|
.ColorScheme-Highlight {
|
||||||
|
color:#3daee9;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<path
|
||||||
|
style="fill:currentColor;fill-opacity:1;stroke:none"
|
||||||
|
d="M 11 3 C 9.558286 3 8.2107109 3.3829219 7.0449219 4.0449219 L 7.7832031 4.7832031 C 7.7832031 4.7832031 7.7851562 4.78125 7.7851562 4.78125 L 10.564453 7.5585938 L 11.271484 6.8515625 L 8.7890625 4.3710938 C 9.4846855 4.1384172 10.223912 4 11 4 C 14.87797 4 18 7.122 18 11 C 18 12.1625 17.714172 13.253897 17.216797 14.216797 L 17.955078 14.955078 C 18.617129 13.789278 19 12.4417 19 11 C 19 6.568 15.431966 3 11 3 z M 4.0449219 7.0449219 C 3.3828709 8.2107219 3 9.5583 3 11 C 3 15.432 6.568034 19 11 19 C 12.441714 19 13.789289 18.617078 14.955078 17.955078 L 14.271484 17.271484 L 14.273438 17.269531 L 11.445312 14.441406 L 10.738281 15.148438 L 13.216797 17.626953 C 12.519497 17.860874 11.778264 18 11 18 C 7.12203 18 4 14.878 4 11 C 4 9.8375 4.2858291 8.7461031 4.7832031 7.7832031 L 4.0449219 7.0449219 z "
|
||||||
|
class="ColorScheme-Text"
|
||||||
|
/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
57
mj/main.css
57
mj/main.css
@ -1,21 +1,52 @@
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: Sans;
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs,
|
||||||
|
body,
|
||||||
|
html {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.card,
|
||||||
|
.cp {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
transition: background-color 200ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cp {
|
||||||
|
color: white;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
display: flex;
|
|
||||||
width: 150px;
|
width: 150px;
|
||||||
height: 220px;
|
height: 220px;
|
||||||
align-items: center;
|
background-color: #d8ecbe;
|
||||||
justify-content: center;
|
|
||||||
background-color: #ddd;
|
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
float: left;
|
float: left;
|
||||||
box-shadow: #000000 1px 1px 7px -1px;
|
box-shadow: #000000 1px 1px 5px -1px;
|
||||||
font-size: 17pt;
|
font-size: 17pt;
|
||||||
color: #4c4c4c;
|
color: #4c4c4c;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
transition: background-color 200ms ease-in-out,
|
transition: background-color 200ms ease-in-out,
|
||||||
opacity 200ms ease-in-out,
|
opacity 200ms ease-in-out,
|
||||||
@ -25,13 +56,23 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
background-color: #76bce2;
|
background-color: #8bc9ee;
|
||||||
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.selected:hover {
|
.card.selected:hover {
|
||||||
background-color: #76bce2;
|
background-color: #8bc9ee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card:hover {
|
.card:hover {
|
||||||
background-color: #e3cfbb;
|
background-color: #e3cfbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #198cfc;
|
||||||
|
box-shadow: #000000 0px 1px 4px 0px;
|
||||||
}
|
}
|
34
mj/main.js
34
mj/main.js
@ -1,4 +1,5 @@
|
|||||||
import Card from './card.js'
|
import Card from './card.js';
|
||||||
|
import Panel from './panel.js';
|
||||||
|
|
||||||
document.body.innerText = "";
|
document.body.innerText = "";
|
||||||
|
|
||||||
@ -25,8 +26,21 @@ const vocabulary = [
|
|||||||
let deck = [];
|
let deck = [];
|
||||||
let selected = null;
|
let selected = null;
|
||||||
|
|
||||||
Card.setBounds(0, 0, window.innerWidth, window.innerHeight)
|
let panel = new Panel();
|
||||||
for (let i = 0; i < 50; ++i) {
|
let field = document.createElement("div");
|
||||||
|
field.classList.add("fs");
|
||||||
|
field.style.position = "relative";
|
||||||
|
panel.append(document.body);
|
||||||
|
panel.installShuffle(reshuffle);
|
||||||
|
document.body.appendChild(field);
|
||||||
|
|
||||||
|
window.onresize = function() {
|
||||||
|
Card.setBounds(0, 0, field.offsetWidth, field.offsetHeight);
|
||||||
|
reshuffle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Card.setBounds(0, 0, field.offsetWidth, field.offsetHeight);
|
||||||
|
for (let i = 0; i < 30; ++i) {
|
||||||
let id = Math.floor(Math.random() * vocabulary.length);
|
let id = Math.floor(Math.random() * vocabulary.length);
|
||||||
let set = vocabulary[id];
|
let set = vocabulary[id];
|
||||||
for (let s = 0; s < set.length; ++s) {
|
for (let s = 0; s < set.length; ++s) {
|
||||||
@ -39,15 +53,18 @@ for (let i = 0; i < 50; ++i) {
|
|||||||
|
|
||||||
deck = shuffle(deck);
|
deck = shuffle(deck);
|
||||||
for (let i = 0; i < deck.length; ++i) {
|
for (let i = 0; i < deck.length; ++i) {
|
||||||
document.body.appendChild(deck[i].element);
|
field.appendChild(deck[i].element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panel.startTimer();
|
||||||
|
|
||||||
function onCardClick(card) {
|
function onCardClick(card) {
|
||||||
if (selected != null) {
|
if (selected != null) {
|
||||||
if (card === selected) {
|
if (card === selected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (selected.setId === card.setId && selected.cardId !== card.cardId) {
|
if (selected.setId === card.setId && selected.cardId !== card.cardId) {
|
||||||
|
card.select();
|
||||||
score(selected, card);
|
score(selected, card);
|
||||||
selected = null;
|
selected = null;
|
||||||
return;
|
return;
|
||||||
@ -69,12 +86,17 @@ function score(c1, c2) {
|
|||||||
c2.position(x, y);
|
c2.position(x, y);
|
||||||
c1.rotate(0);
|
c1.rotate(0);
|
||||||
c2.rotate(0);
|
c2.rotate(0);
|
||||||
c1.element.style.zIndex = "5";
|
|
||||||
c2.element.style.zIndex = "5";
|
|
||||||
|
|
||||||
setTimeout(fade.bind(null, c1, c2), 200);
|
setTimeout(fade.bind(null, c1, c2), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reshuffle() {
|
||||||
|
for (let i = 0; i < deck.length; ++i) {
|
||||||
|
deck[i].disrotate();
|
||||||
|
deck[i].displace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function fade(c1, c2) {
|
function fade(c1, c2) {
|
||||||
c1.destructor();
|
c1.destructor();
|
||||||
c2.destructor();
|
c2.destructor();
|
||||||
|
123
mj/panel.js
Normal file
123
mj/panel.js
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
const height = 100;
|
||||||
|
|
||||||
|
class Panel {
|
||||||
|
constructor() {
|
||||||
|
this.element = document.createElement("div");
|
||||||
|
this.element.classList.add("panel")
|
||||||
|
this.element.style.height = height + "px";
|
||||||
|
|
||||||
|
this._createLeftPanel();
|
||||||
|
this._createRightPanel();
|
||||||
|
this._createCentralPanel();
|
||||||
|
|
||||||
|
this._shuffle = null;
|
||||||
|
|
||||||
|
this._time = null;
|
||||||
|
|
||||||
|
this._updateInterval = setInterval(this._update.bind(this), 53);
|
||||||
|
}
|
||||||
|
destructor() {
|
||||||
|
this.element.remove();
|
||||||
|
}
|
||||||
|
append(element) {
|
||||||
|
element.style.position = "relative";
|
||||||
|
element.style.paddingTop = height + "px";
|
||||||
|
element.appendChild(this.element);
|
||||||
|
}
|
||||||
|
installShuffle(func) {
|
||||||
|
this._shuffle = func;
|
||||||
|
}
|
||||||
|
startTimer() {
|
||||||
|
this._time = Date.now();
|
||||||
|
}
|
||||||
|
_createLeftPanel() {
|
||||||
|
this._leftPanel = document.createElement("div");
|
||||||
|
this._leftPanel.style.position = "absolute";
|
||||||
|
this._leftPanel.style.top = "0";
|
||||||
|
this._leftPanel.style.left = "0";
|
||||||
|
|
||||||
|
this._shuffleButton = document.createElement("div");
|
||||||
|
this._shuffleButton.classList.add("button");
|
||||||
|
this._shuffleButton.style.backgroundImage = "url(icons/refresh.svg)";
|
||||||
|
this._shuffleButton.style.height = height + "px";
|
||||||
|
this._shuffleButton.style.width = height + "px";
|
||||||
|
this._shuffleButton.style.position = "absolute";
|
||||||
|
this._shuffleButton.style.top = "0";
|
||||||
|
this._shuffleButton.style.left = "0";
|
||||||
|
this._shuffleButton.title = "Shuffle";
|
||||||
|
this._shuffleButton.addEventListener("click", this._onShuffle.bind(this));
|
||||||
|
|
||||||
|
this._leftPanel.appendChild(this._shuffleButton);
|
||||||
|
|
||||||
|
this.element.style.paddingLeft = height + "px";
|
||||||
|
this.element.appendChild(this._leftPanel);
|
||||||
|
}
|
||||||
|
_createRightPanel() {
|
||||||
|
this._rightPanel = document.createElement("div");
|
||||||
|
this._rightPanel.style.position = "absolute";
|
||||||
|
this._rightPanel.style.top = "0";
|
||||||
|
this._rightPanel.style.right = "0";
|
||||||
|
this.element.appendChild(this._rightPanel);
|
||||||
|
}
|
||||||
|
_createCentralPanel() {
|
||||||
|
this._centralPanel = document.createElement("div");
|
||||||
|
this._centralPanel.classList.add("fs", "cp");
|
||||||
|
this._centralPanel.style.display = "flex";
|
||||||
|
this._centralPanel.style.alignItems = "center";
|
||||||
|
this._centralPanel.style.justifyContent = "center";
|
||||||
|
|
||||||
|
this._ms = document.createElement("span");
|
||||||
|
this._mds = document.createElement("span");
|
||||||
|
this._ss = document.createElement("span");
|
||||||
|
this._sdmin = document.createElement("span");
|
||||||
|
this._mins = document.createElement("span");
|
||||||
|
|
||||||
|
this._ms.innerText = "000";
|
||||||
|
this._mds.innerText = ":";
|
||||||
|
this._ss.innerText = "00";
|
||||||
|
this._sdmin.innerText = ":";
|
||||||
|
this._mins.innerText = "00";
|
||||||
|
|
||||||
|
this._centralPanel.appendChild(this._mins);
|
||||||
|
this._centralPanel.appendChild(this._sdmin);
|
||||||
|
this._centralPanel.appendChild(this._ss);
|
||||||
|
this._centralPanel.appendChild(this._mds);
|
||||||
|
this._centralPanel.appendChild(this._ms);
|
||||||
|
|
||||||
|
this.element.appendChild(this._centralPanel);
|
||||||
|
}
|
||||||
|
_update() {
|
||||||
|
if (this._time !== null) {
|
||||||
|
let time = Date.now() - this._time;
|
||||||
|
let minutes = Math.floor(time / (1000 * 60));
|
||||||
|
time = time % (1000 * 60);
|
||||||
|
let seconds = Math.floor(time / 1000);
|
||||||
|
time = time % 1000;
|
||||||
|
|
||||||
|
this._mins.innerText = pad(minutes, 2);
|
||||||
|
this._ss.innerText = pad(seconds, 2);
|
||||||
|
this._ms.innerText = pad(time, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_onShuffle() {
|
||||||
|
if (this._shuffle !== null) {
|
||||||
|
this._shuffle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pad (num, amount) {
|
||||||
|
let p = pads[amount];
|
||||||
|
let sNum = num.toString();
|
||||||
|
let pref = p[sNum.length];
|
||||||
|
return pref + sNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pads = [
|
||||||
|
[""],
|
||||||
|
["0", ""],
|
||||||
|
["00", "0", ""],
|
||||||
|
["000", "00", "0", ""]
|
||||||
|
]
|
||||||
|
|
||||||
|
export default Panel;
|
Loading…
Reference in New Issue
Block a user