light and darkmode change logic & disable buttons after start spin & format

This commit is contained in:
p-wojt 2022-01-12 23:33:44 +01:00
parent 3707a32c94
commit 6811b6d771
10 changed files with 208 additions and 191 deletions

21
app.css
View File

@ -1,6 +1,6 @@
body { body {
background-color: #121212; background-color: #121212;
color: #FAF9F6; color: #faf9f6;
transition-duration: 3s; transition-duration: 3s;
} }
@ -45,25 +45,24 @@ ul {
text-align: center; text-align: center;
} }
.add-item-button { .add-item-button {
height: 2rem; height: 2rem;
width: 15.5rem; width: 15.5rem;
margin-top: 0.5rem; margin-top: 0.5rem;
background-color: #6495ED; background-color: #6495ed;
border: 0.05rem solid black; border: 0.05rem solid black;
box-shadow: 0 0.7rem 0 -0.1rem #6082B6, 0 0.75rem 0 -0.05rem black; box-shadow: 0 0.7rem 0 -0.1rem #6082b6, 0 0.75rem 0 -0.05rem black;
border-radius: 0.5rem; border-radius: 0.5rem;
} }
.add-item-button:hover { .add-item-button:hover {
transform: translate(0, 0.25rem); transform: translate(0, 0.25rem);
box-shadow: 0 0.5rem 0 -0.1rem #6082B6, 0 0.55rem 0 -0.05rem black; box-shadow: 0 0.5rem 0 -0.1rem #6082b6, 0 0.55rem 0 -0.05rem black;
} }
.add-item-button:active { .add-item-button:active {
transform: translate(0, 0.5rem); transform: translate(0, 0.5rem);
box-shadow: 0 0.1rem 0 -0.1rem #6082B6, 0 0.15rem 0 -0.05rem black; box-shadow: 0 0.1rem 0 -0.1rem #6082b6, 0 0.15rem 0 -0.05rem black;
} }
.counter { .counter {
@ -98,20 +97,20 @@ ul {
.remove-all-items-button { .remove-all-items-button {
width: 5.4rem; width: 5.4rem;
height: 2rem; height: 2rem;
background-color: #6495ED; background-color: #6495ed;
border: 0.05rem solid black; border: 0.05rem solid black;
box-shadow: 0 0.7rem 0 -0.1rem #6082B6, 0 0.75rem 0 -0.05rem black; box-shadow: 0 0.7rem 0 -0.1rem #6082b6, 0 0.75rem 0 -0.05rem black;
border-radius: 0.5rem; border-radius: 0.5rem;
} }
.remove-all-items-button:hover { .remove-all-items-button:hover {
transform: translate(0, 0.25rem); transform: translate(0, 0.25rem);
box-shadow: 0 0.5rem 0 -0.1rem #6082B6, 0 0.55rem 0 -0.05rem black; box-shadow: 0 0.5rem 0 -0.1rem #6082b6, 0 0.55rem 0 -0.05rem black;
} }
.remove-all-items-button:active { .remove-all-items-button:active {
transform: translate(0, 0.5rem); transform: translate(0, 0.5rem);
box-shadow: 0 0.1rem 0 -0.1rem #6082B6, 0 0.15rem 0 -0.05rem black; box-shadow: 0 0.1rem 0 -0.1rem #6082b6, 0 0.15rem 0 -0.05rem black;
} }
.roulette-wheel { .roulette-wheel {
@ -129,7 +128,7 @@ ul {
} }
.winner { .winner {
font-size: 32; font-size: 32px;
margin-bottom: 1rem; margin-bottom: 1rem;
height: 28px; height: 28px;
} }

View File

@ -10,7 +10,7 @@
</head> </head>
<body> <body>
<div class="light-dark-mode"> <div class="light-dark-mode">
<img class="moon-sun" src='static/moon.png' alt="mode"> <img class="moon-sun" src="static/moon.png" alt="mode" />
</div> </div>
<div class="menu"> <div class="menu">
<p class="counter"></p> <p class="counter"></p>
@ -26,7 +26,12 @@
</div> </div>
<footer> <footer>
<div hidden="true" class="icons-authors"> <div hidden="true" class="icons-authors">
<img class="moon-sun" src='static/moon.png' alt="mode"> <img class="moon-sun" src='static/sun.png' alt="mode"> Made by made by <a href="https://www.freepik.com" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> <img class="moon-sun" src="static/moon.png" alt="mode" />
<img class="moon-sun" src="static/sun.png" alt="mode" /> Made by made by
<a href="https://www.freepik.com" title="Freepik">Freepik</a> from
<a href="https://www.flaticon.com/" title="Flaticon"
>www.flaticon.com</a
>
</div> </div>
<p>Icons</p> <p>Icons</p>
</footer> </footer>

View File

@ -22,15 +22,20 @@ const lightDarkModeEl = document.getElementsByClassName(
"light-dark-mode" "light-dark-mode"
)[0]! as HTMLDivElement; )[0]! as HTMLDivElement;
const canvasEl = document.querySelector("canvas")! as HTMLCanvasElement; const canvasEl = document.querySelector("canvas")! as HTMLCanvasElement;
const ctx = canvasEl.getContext("2d")!;
const bodyEl = document.querySelector("body")! as HTMLBodyElement; const bodyEl = document.querySelector("body")! as HTMLBodyElement;
const modeEl = lightDarkModeEl.querySelector("img")! as HTMLImageElement; const modeEl = lightDarkModeEl.querySelector("img")! as HTMLImageElement;
const canvasWrapper = document.getElementsByClassName(
"roulette-wheel"
)[0]! as HTMLDivElement;
const winnerEl = document.getElementsByClassName( const winnerEl = document.getElementsByClassName(
"winner" "winner"
)[0]! as HTMLDivElement; )[0]! as HTMLDivElement;
const footerEl = document.querySelector("footer")!;
const authorsEl = document.getElementsByClassName(
"icons-authors"
)[0]! as HTMLDivElement;
const canvasWrapper = document.getElementsByClassName(
"roulette-wheel"
)[0]! as HTMLDivElement;
const ctx = canvasEl.getContext("2d")!;
canvasEl.width = canvasWrapper.offsetWidth; canvasEl.width = canvasWrapper.offsetWidth;
canvasEl.height = canvasWrapper.offsetHeight; canvasEl.height = canvasWrapper.offsetHeight;
@ -47,12 +52,12 @@ const itemsList = new ItemList(MAXIMUM_SIZE);
const items: MenuItem[] = []; const items: MenuItem[] = [];
let rotate_by = 50; let rotate_by = 50;
let totalTime = 0;
configure(); configure();
function configure() { function configure() {
counterEl.textContent = `0/${MAXIMUM_SIZE}`; counterEl.textContent = `0/${MAXIMUM_SIZE}`;
winnerEl.style.fontSize = "32px";
LightDarkMode.currentMode = "dark"; LightDarkMode.currentMode = "dark";
IdPool.initializeIdsPool(MAXIMUM_SIZE); IdPool.initializeIdsPool(MAXIMUM_SIZE);
@ -63,10 +68,16 @@ function configure() {
drawRouletteWheel(0); drawRouletteWheel(0);
canvasEl.addEventListener("click", startRoulette); canvasEl.addEventListener("click", startRoulette);
footerEl.addEventListener("click", () => {
authorsEl.hidden = !authorsEl.hidden;
});
} }
function addRemoveItem() { function addRemoveItem() {
addButtonEl.addEventListener("click", () => { addButtonEl.addEventListener("click", () => {
if (!animationId) {
clearWinner();
const name = inputEl.value; const name = inputEl.value;
if (name) { if (name) {
const id = IdPool.getAnId(); const id = IdPool.getAnId();
@ -76,12 +87,15 @@ function addRemoveItem() {
const menuItem = new MenuItem(id, name, color); const menuItem = new MenuItem(id, name, color);
menuItem.deleteItem.el.addEventListener("click", () => { menuItem.deleteItem.el.addEventListener("click", () => {
if (!animationId) {
clearWinner();
menuItem.el.remove(); menuItem.el.remove();
items.splice(items.indexOf(menuItem), 1); items.splice(items.indexOf(menuItem), 1);
itemsList.remove(item); itemsList.remove(item);
IdPool.addId(item.id); IdPool.addId(item.id);
updateCounter(); updateCounter();
drawRouletteWheel(0); drawRouletteWheel(0);
}
}); });
registerChangeColorByClick(item, menuItem); registerChangeColorByClick(item, menuItem);
@ -96,6 +110,7 @@ function addRemoveItem() {
drawRouletteWheel(0); drawRouletteWheel(0);
} }
} }
}
}); });
} }
@ -108,6 +123,7 @@ function addItemByEnter() {
function registerChangeColorByClick(item: Item, menuItem: MenuItem) { function registerChangeColorByClick(item: Item, menuItem: MenuItem) {
menuItem.el.addEventListener("click", () => { menuItem.el.addEventListener("click", () => {
if (!animationId) {
const actualColorIndex = avaliableRGBs.indexOf( const actualColorIndex = avaliableRGBs.indexOf(
menuItem.el.style.backgroundColor menuItem.el.style.backgroundColor
); );
@ -116,13 +132,16 @@ function registerChangeColorByClick(item: Item, menuItem: MenuItem) {
avaliableRGBs[(actualColorIndex + 1) % avaliableRGBs.length]; avaliableRGBs[(actualColorIndex + 1) % avaliableRGBs.length];
menuItem.el.style.backgroundColor = color; menuItem.el.style.backgroundColor = color;
item.color = color; item.color = color;
if (!animationId) drawRouletteWheel(0); drawRouletteWheel(0);
}
} }
}); });
} }
function removeAllItems() { function removeAllItems() {
removeAllItemsButtonEl.addEventListener("click", () => { removeAllItemsButtonEl.addEventListener("click", () => {
if (!animationId) {
clearWinner();
if (items.length > 0) { if (items.length > 0) {
items.forEach((menuItem) => menuItem.el.remove()); items.forEach((menuItem) => menuItem.el.remove());
items.length = 0; items.length = 0;
@ -131,9 +150,32 @@ function removeAllItems() {
updateCounter(); updateCounter();
drawRouletteWheel(0); drawRouletteWheel(0);
} }
}
}); });
} }
function lightDarkMode() {
lightDarkModeEl.addEventListener("click", () => {
modeEl.animate([{ transform: "rotate(360deg)" }], {
duration: 500,
});
if (LightDarkMode.currentMode == "dark") {
modeEl.src = "static/sun.png";
bodyEl.style.backgroundColor = "#FAF9F6";
bodyEl.style.color = "black";
LightDarkMode.currentMode = "light";
} else {
modeEl.src = "static/moon.png";
bodyEl.style.backgroundColor = "#121212";
bodyEl.style.color = "white";
LightDarkMode.currentMode = "dark";
}
});
}
function updateCounter() { function updateCounter() {
counterEl.textContent = `${itemsList.items.length}/${MAXIMUM_SIZE}`; counterEl.textContent = `${itemsList.items.length}/${MAXIMUM_SIZE}`;
animateCounter(); animateCounter();
@ -141,11 +183,7 @@ function updateCounter() {
function animateCounter() { function animateCounter() {
counterEl.animate( counterEl.animate(
[ [{ transform: "scale(1.5)" }, { transform: "scale(1.00)" }],
{ transform: "scale(1.5)" },
{ transform: "scale(1.00)" },
{ transform: "" },
],
{ {
duration: 500, duration: 500,
} }
@ -162,25 +200,6 @@ function animateWinner() {
); );
} }
function lightDarkMode() {
lightDarkModeEl.addEventListener("click", () => {
modeEl.animate([{ transform: "rotate(360deg)" }], {
duration: 500,
});
if (LightDarkMode.currentMode == "dark") {
modeEl.src = "static/sun.png";
bodyEl.style.backgroundColor = "#FAF9F6";
bodyEl.style.color = "black";
} else {
modeEl.src = "static/moon.png";
bodyEl.style.backgroundColor = "#121212";
bodyEl.style.color = "white";
}
LightDarkMode.changeMode();
});
}
function drawRouletteWheel(angle: number) { function drawRouletteWheel(angle: number) {
const segmentWidth = 360 / items.length; const segmentWidth = 360 / items.length;
let startAngle = angle; let startAngle = angle;
@ -242,24 +261,14 @@ let animationId: number | null;
let winner: string; let winner: string;
let endTime: number; let endTime: number;
function easeOut(
time: number,
beginningVal: number,
toChange: number,
duration: number
) {
return time == duration
? beginningVal + toChange
: toChange * (-Math.pow(2, (-10 * time) / duration) + 1) + beginningVal;
}
function startRoulette() { function startRoulette() {
if (!animationId) { if (!animationId) {
if (winner) { const winnerCleared = clearWinner();
winner = ""; if (winnerCleared) {
winnerEl.textContent = "";
drawRouletteWheel(0); drawRouletteWheel(0);
} else { } else {
addButtonEl.style.background = "#C0C0C0";
removeAllItemsButtonEl.style.background = "#C0C0C0";
guessItemIndex = Math.floor(Math.random() * items.length); guessItemIndex = Math.floor(Math.random() * items.length);
winner = itemsList.items[guessItemIndex].name; winner = itemsList.items[guessItemIndex].name;
segmentAngle = 360 / items.length; segmentAngle = 360 / items.length;
@ -274,8 +283,15 @@ function startRoulette() {
} }
} }
function clearWinner() {
if (winner) {
winner = "";
winnerEl.textContent = "";
return true;
}
return false;
}
let totalTime = 0;
function beginAnimateRoulette() { function beginAnimateRoulette() {
const angle = easeOut(totalTime, 0, maxAngle, endTime); const angle = easeOut(totalTime, 0, maxAngle, endTime);
if (totalTime < endTime || maxAngle - angle > 0.1) { if (totalTime < endTime || maxAngle - angle > 0.1) {
@ -288,12 +304,20 @@ function beginAnimateRoulette() {
window.cancelAnimationFrame(animationId!); window.cancelAnimationFrame(animationId!);
animationId = null; animationId = null;
winnerEl.textContent = `Winner: ${winner}`; winnerEl.textContent = `Winner: ${winner}`;
addButtonEl.style.background = "#6082B6";
removeAllItemsButtonEl.style.background = "#6082B6";
animateWinner(); animateWinner();
} }
} }
const footerEl = document.querySelector('footer')!;
const authorsEl = document.getElementsByClassName('icons-authors')[0]! as HTMLDivElement; function easeOut(
footerEl.addEventListener('click', () => { time: number,
authorsEl.hidden = !authorsEl.hidden; beginningVal: number,
}); toChange: number,
duration: number
) {
return time == duration
? beginningVal + toChange
: toChange * (-Math.pow(2, (-10 * time) / duration) + 1) + beginningVal;
}

View File

@ -1,13 +1,12 @@
import { Component } from "./base-component"; import { Component } from "./base-component";
export class ItemRemoval extends Component<HTMLImageElement> { export class ItemRemoval extends Component<HTMLImageElement> {
constructor(id: number) { constructor(id: number) {
const el = document.createElement('img'); const el = document.createElement("img");
el.src = 'static/close.png'; el.src = "static/close.png";
el.alt = 'delete'; el.alt = "delete";
el.className = `item-delete`; el.className = `item-delete`;
el.id = `${id}-delete` el.id = `${id}-delete`;
super(el); super(el);
} }
} }

View File

@ -2,13 +2,12 @@ import { Component } from "./base-component";
import { ItemRemoval } from "./item-removal"; import { ItemRemoval } from "./item-removal";
export class MenuItem extends Component<HTMLLIElement> { export class MenuItem extends Component<HTMLLIElement> {
deleteItem: ItemRemoval; deleteItem: ItemRemoval;
constructor(id: number, name: string, color: string) { constructor(id: number, name: string, color: string) {
const deleteItem = new ItemRemoval(id); const deleteItem = new ItemRemoval(id);
const el = document.createElement('li'); const el = document.createElement("li");
el.className = 'menu-item'; el.className = "menu-item";
el.id = `${id}-item`; el.id = `${id}-item`;
el.textContent = name; el.textContent = name;
el.style.backgroundColor = color; el.style.backgroundColor = color;

View File

@ -11,12 +11,11 @@ export class ItemList implements List<Item> {
} }
add(item: Item) { add(item: Item) {
if(this.items.length < this.maximumSize) if (this.items.length < this.maximumSize) this.items.push(item);
this.items.push(item);
} }
removeById(id: number) { removeById(id: number) {
const toRemove = this.items.find(e => e.id === id); const toRemove = this.items.find((e) => e.id === id);
if (toRemove) { if (toRemove) {
this.remove(toRemove); this.remove(toRemove);
} }

View File

@ -1,13 +1,5 @@
type mode = 'dark' | 'light'; type mode = "dark" | "light";
export abstract class LightDarkMode { export abstract class LightDarkMode {
static currentMode: mode; static currentMode: mode;
static changeMode(){
if(this.currentMode == 'light'){
this.currentMode = 'dark';
}else{
this.currentMode = 'light';
}
}
} }