diff --git a/src/app.html b/src/app.html index 8f206f421491cce6eae6d8cbb2b291f284194d75..ec070ff769d55d660d9bb21136e4ab81b553ed7b 100644 --- a/src/app.html +++ b/src/app.html @@ -19,7 +19,7 @@ %sveltekit.head% </head> - <body data-sveltekit-preload-data="hover"> + <body data-sveltekit-preload-data="hover" class="bg-random-500"> <div style="display: contents">%sveltekit.body%</div> </body> </html> diff --git a/src/routes/pokemon/+page.svelte b/src/routes/pokemon/+page.svelte deleted file mode 100644 index c71e45816a865b05e158548e4fc9953fb6d35761..0000000000000000000000000000000000000000 --- a/src/routes/pokemon/+page.svelte +++ /dev/null @@ -1,291 +0,0 @@ -<script lang="ts"> - import "./style.css"; - import { onMount } from "svelte"; - - const pkmnTotal = 802; - const url = `https://pokeapi.co/api/v2/pokemon/?limit=${pkmnTotal}`; - const optionAmount = 4; - let pokemonData: Answer[] = []; - const prettyNames = { - "nidoran-f": "nidoran♀", - "nidoran-m": "nidoran♂", - "mr-mime": "mr. mime", - "deoxys-normal": "deoxys", - "wormadam-plant": "wormadam", - "mime-jr": "mime jr.", - "giratina-altered": "giratina", - "shaymin-land": "shaymin", - "basculin-red-striped": "basculin", - "darmanitan-standard": "darmanitan", - "tornadus-incarnate": "tornadus", - "thundurus-incarnate": "thundurus", - "landorus-incarnate": "landorus", - "keldeo-ordinary": "keldeo", - "meloetta-aria": "meloetta", - "meowstic-male": "meowstic", - "aegislash-shield": "aegislash", - "pumpkaboo-average": "pumpkaboo", - "gourgeist-average": "gourgeist", - "oricorio-baile": "oricorio", - "lycanroc-midday": "lycanroc", - "wishiwashi-solo": "wishiwashi", - "type-null": "type: null", - "minior-red-meteor": "minior", - "mimikyu-disguised": "mimikyu", - "tapu-koko": "tapu koko", - "tapu-lele": "tapu lele", - "tapu-bulu": "tapu bulu", - "tapu-fini": "tapu fini", - }; - - type Answer = { - url: string; - name: string; - index: number; - }; - - let pokemon: Answer[] = []; - let pkmnAmount = 0; - let score = 0; - let question = 0; - let questionAmount = 10; - let answer: Answer | null = null; - let selected: Answer | null = null; - let options: Answer[] = []; - let isPlaying = false; - let isDone = false; - let isChecked = false; - let trainerHovered: string | null = null; - - let image: string; - - $: classic = pkmnAmount <= 151; - $: if (answer) { - image = getImage(classic, answer); - } - - function getImage(classic: boolean, answer: Answer) { - let url = - "https://raw.githubusercontent.com/tiffachoo/pokesprites/master/pokemon/"; - let imageUrl = `${url}${classic ? "redblue" : "sunmoon"}/`; - let number = answer.url.match(/\/(\d+)/)![1]; - return `${imageUrl}${number}.png`; - } - - onMount(() => { - let pokeList = localStorage.getItem("pokeList"); - - if (pokeList) { - pokemonData = JSON.parse(pokeList); - } else { - getData().then((res) => { - pokemonData = res.results; - localStorage.setItem("pokeList", JSON.stringify(res.results)); - }); - } - }); - - function prettifyName(name: string) { - return prettyNames[name as keyof typeof prettyNames] || name; - } - - function getData() { - return fetch(url) - .then((res) => res.json()) - .catch((err) => console.log("errrr")); - } - function startGame(val: number) { - question = 0; - score = 0; - isPlaying = true; - pokemon = [...pokemonData]; - - pkmnAmount = val || pkmnTotal; - - getNextQuestion(); - } - function getNextQuestion() { - question += 1; - resetAnswer(); - - if (question <= questionAmount) { - let removed: Answer; - for (let i = 1; i <= optionAmount; i++) { - removed = pokemon.splice(getRandomPokemon(i), 1)[0]; - if (i === 1) { - answer = removed; - } else { - options.push(removed); - } - } - - let pos = Math.floor(Math.random() * optionAmount); - options.splice(pos, 0, answer as Answer); - } else { - isPlaying = false; - isDone = true; - resetAnswer(); - } - } - function selectAnswer(ans: Answer) { - if (!isChecked) { - selected = ans; - } - } - function checkAnswer() { - isChecked = true; - - if (selected && answer && selected.name === answer.name) { - score += 10; - } - } - function getRandomPokemon(index: number) { - const diff = (question - 1) * 4 + index; - return Math.floor(Math.random() * (pkmnAmount + 1 - diff)); - } - function resetAnswer() { - options = []; - selected = null; - answer = null; - isChecked = false; - } - function restartGame() { - isDone = false; - } - - function trainerHover(val: string | MouseEvent | FocusEvent) { - trainerHovered = val as string; - } -</script> - -<div id="app"> - <div class:poke-classic={classic} class="container"> - <transition name="animate-section"> - {#if !isPlaying && !isDone} - <section class="poke-section"> - <h2>What type of trainer are you?</h2> - <div class="poke-intro-trainer"> - <div class="poke-ball"></div> - <img - class:active={trainerHovered === "classic"} - class="poke-trainer-img poke-trainer-img-classic" - src="https://raw.githubusercontent.com/tiffachoo/pokesprites/master/trainers/red-rb.png" - alt="Trainer red" - /> - <img - class:active={trainerHovered === "master"} - class="poke-trainer-img poke-trainer-img-master" - src="https://raw.githubusercontent.com/tiffachoo/pokesprites/master/trainers/red-sm.png" - alt="Trainer red again" - /> - </div> - <button - class="button spacer" - on:click={() => startGame(151)} - on:mouseover={() => trainerHover("classic")} - on:focus={() => trainerHover("classic")} - on:mouseout={trainerHover} - on:blur={trainerHover} - > - Classic - </button> - <button - class="button" - on:click={() => startGame(0)} - on:mouseover={() => trainerHover("master")} - on:focus={() => trainerHover("master")} - on:mouseout={trainerHover} - on:blur={trainerHover} - > - Master - </button> - </section> - {/if} - </transition> - - <transition name="animate-section"> - {#if isPlaying} - <section class="poke-section"> - <h1 class="poke-title">Who's that pokemon?</h1> - <div class="poke-question-wrapper"> - <span class="poke-question"> - <span class="poke-question-number"> - {question} - </span> - <span class="poke-question-amount"> - / {questionAmount} - </span> - </span> - <span class="poke-score"> - {score} - <small>pts</small> - </span> - <div - class="poke-image" - class:poke-image-success={isChecked && - selected && - answer && - selected.name === answer.name} - class:poke-image-error={isChecked && - selected && - answer && - selected.name !== answer.name} - > - <img src={image} alt="No cheating" class="poke-image-img" /> - </div> - <transition-group - tag="div" - name="animate-options" - class:poke-options-answers={isChecked} - class="poke-options" - > - {#each options as pokemon, index} - <button - data-index={index} - class:selected={selected && selected.index === index} - class:success={isChecked && - answer && - pokemon.name === answer.name} - class:error={isChecked && - selected && - answer && - selected.index === index && - selected.name !== answer.name} - class="poke-options-button" - on:click={() => selectAnswer({ ...pokemon, index })} - >{prettifyName(pokemon.name)}</button - > - {/each} - </transition-group> - <footer class="poke-buttons"> - <button - disabled={isChecked || - (selected && Object.keys(selected).length < 1)} - class="button" - on:click={checkAnswer}>Submit</button - > - <button - disabled={!isChecked} - class="button" - on:click={getNextQuestion}>Next</button - > - </footer> - </div> - </section> - {/if} - </transition> - - <transition name="animate-section"> - {#if isDone} - <section class="poke-final"> - <h2>Final score</h2> - <span class="poke-final-score"> - <span class="poke-final-score-number">{score}</span> - pts - </span> - <button class="button" on:click={restartGame}>Play again</button> - </section> - {/if} - </transition> - </div> -</div> diff --git a/src/routes/pokemon/style.css b/src/routes/pokemon/style.css deleted file mode 100644 index 3c251cf45970cee3073c0614702738767cc3b1ed..0000000000000000000000000000000000000000 --- a/src/routes/pokemon/style.css +++ /dev/null @@ -1,460 +0,0 @@ -@import "https://fonts.googleapis.com/css?family=VT323"; -* { - box-sizing: border-box; -} - -body { - background-color: #f65a52; - font-family: "VT323", monospace; - font-size: 16px; - line-height: 1.875em; - color: #333; -} - -.container { - width: 100%; - max-width: 400px; - position: relative; - margin: 50px auto; -} - -h2 { - font-size: 1.25rem; - white-space: nowrap; -} - -.spacer { - margin-bottom: 0.5rem; -} - -.button { - padding: 0.5em 1.5em; - border-radius: 1rem; - border: solid 1px transparent; - font-family: "VT323", monospace; - font-size: 1.5rem; - background-color: #f32c22; - color: #333; - cursor: pointer; - transition: 0.35s; -} -.button:focus { - outline: none; - border: 1px dotted #f87f79; -} -.button:not([disabled]):hover { - background-color: #333; - color: #f65a52; -} - -.poke-section { - display: flex; - flex-direction: column; - align-items: center; - position: relative; - max-width: 500px; - margin: auto; -} - -.poke-intro-trainer { - position: relative; - margin-bottom: 1rem; - height: 200px; - width: 200px; -} -.poke-intro-trainer .poke-trainer-img { - position: absolute; - left: 50%; - bottom: 0; - height: 200px; - opacity: 0; - transition: 0.4s cubic-bezier(0.22, 0.75, 0.53, 0.99); -} -@media (max-width: 479px) { - .poke-intro-trainer .poke-trainer-img { - display: none; - } -} -.poke-intro-trainer .poke-trainer-img.active { - transform: translateX(-50%); - opacity: 1; -} -.poke-intro-trainer .poke-trainer-img-classic { - bottom: 5px; - height: 180px; - -ms-interpolation-mode: nearest-neighbor; - image-rendering: -moz-crisp-edges; - image-rendering: pixelated; - transform: translateX(-80%); -} -.poke-intro-trainer .poke-trainer-img-master { - transform: translateX(-20%); -} - -.poke-ball { - position: absolute; - top: 50%; - left: 50%; - height: 150px; - width: 150px; - border-radius: 50%; - background-color: #f32c22; - transform: translate(-50%, -50%); - overflow: hidden; -} -.poke-ball::before, -.poke-ball::after { - content: ""; - position: absolute; -} -.poke-ball::before { - z-index: 2; - top: 50%; - left: 50%; - height: 40px; - width: 40px; - border-radius: 50%; - border: solid 6px #f65a52; - background-color: #fa9f9b; - transform: translate(-50%, -50%); -} -.poke-ball::after { - z-index: 1; - top: 50%; - height: 50%; - width: 100%; - border-top: solid 6px #f65a52; - background-color: #fa9f9b; -} - -.poke-title { - position: absolute; - top: -2rem; -} - -.poke-question { - position: absolute; - right: calc(100% + 0.5rem); - display: flex; - flex-direction: column; - align-items: flex-end; -} -.poke-question-wrapper { - position: relative; - width: 250px; -} -.poke-question-number { - font-size: 8rem; - line-height: 0.4; - color: #fa9f9b; -} - -.poke-score { - position: absolute; - top: 6rem; - right: calc(100% + 0.5rem); - padding-top: 1rem; - font-size: 1.25rem; - white-space: nowrap; - color: #333; -} -.poke-score::before { - content: ""; - position: absolute; - top: 0; - right: 0; - width: 40px; - height: 6px; - background-color: #333; -} - -.poke-image { - position: relative; - z-index: 2; - display: flex; - justify-content: center; - align-items: center; - width: 250px; - height: 250px; - border-radius: 1rem; - border: solid 6px #333; - background-color: #fff; - overflow: hidden; -} -.poke-image::before, -.poke-image::after { - content: ""; - position: absolute; - z-index: -1; - border-radius: 50%; -} -.poke-image::before { - width: 100px; - height: 100px; - background-color: #c5d5ee; - opacity: 1; - transition: 0.65s ease-in-out; -} -.poke-image::after { - width: 100px; - height: 100px; - border: solid 12px #c5d5ee; - transform: scale(0); - transition: 0.4s ease-in-out; -} -.poke-image-img { - width: auto; - height: 150px; -} -.poke-image-success::before, -.poke-image-error::before { - transform: scale(4); - opacity: 0.5; -} -.poke-image-success::after, -.poke-image-error::after { - transform: scale(1); -} -.poke-image-success::before { - background-color: #7bd55a; -} -.poke-image-success::after { - border-color: #7bd55a; -} -.poke-image-error::before { - background-color: #ff8b62; -} -.poke-image-error::after { - border-color: #ff8b62; - width: 10px; - border-radius: 1rem; - transform: rotate(45deg); -} - -.poke-options { - position: relative; - display: flex; - flex-direction: column; - align-items: center; - z-index: 3; - top: -30px; - padding: 0 20px; - margin: 0 auto; - width: 170px; - border-radius: 1rem; - background-color: #333; -} -.poke-options:not(.poke-options-answers) - .poke-options-button:not(.selected):hover { - background-color: #a9c1e6; - transform: translateY(-3px); -} -.poke-options:not(.poke-options-answers) - .poke-options-button:not(.selected):active::before { - transform: translate(-50%, -50%) scale(1); -} -.poke-options.poke-options-answers .poke-options-button { - cursor: default; -} -.poke-options.poke-options-answers - .poke-options-button:not(.error):not(.success) { - color: #94acbd; -} -.poke-options-button { - position: relative; - width: 100%; - padding: 0.5em; - min-width: 200px; - max-height: 48px; - border: solid 6px #333; - border-radius: 1rem; - background-color: #c5d5ee; - font-family: "VT323", monospace; - font-size: 1.125rem; - transition: 0.45s; - cursor: pointer; - overflow: hidden; -} -.poke-options-button:focus { - outline: none; -} -.poke-options-button::before { - content: ""; - position: absolute; - z-index: -1; - left: 50%; - top: 50%; - height: 200px; - width: 200px; - border-radius: 50%; - background-color: #94acbd; - transform: translate(-50%, -50%) scale(0); - transition: 0.2s ease-in-out; -} -.poke-options-button:not(:last-child) { - margin-bottom: 3px; -} -.poke-options-button.selected { - background-color: #94acbd; -} -.poke-options-button.error { - background-color: #ff8b62; -} -.poke-options-button.success { - background-color: #7bd55a; -} - -.poke-buttons { - text-align: center; -} -@media (min-width: 480px) { - .poke-buttons { - position: absolute; - top: 20px; - left: 100%; - } - .poke-buttons .button { - padding-left: calc(1em + 10px); - border-top-left-radius: 0; - border-bottom-left-radius: 0; - transform: translateX(-10px); - } -} -.poke-buttons .button { - padding: 1em; - width: 110px; - height: 100px; - color: #fff; -} -.poke-buttons .button[disabled] { - color: #fa9f9b; - opacity: 0.7; - cursor: default; -} -.poke-buttons .button:not([disabled]):hover { - transform: translateX(0); -} -.poke-buttons .button:not(:last-child) { - margin-bottom: 6px; -} - -.poke-final { - text-align: center; -} -.poke-final-score { - display: block; - position: relative; - margin-bottom: 1rem; -} -.poke-final-score::before { - content: ""; - position: absolute; - z-index: -1; - top: 50%; - left: 50%; - height: 100px; - width: 100px; - border-radius: 50%; - border: solid 12px #f32c22; - transform: translate(-50%, -50%); - opacity: 0.3; - -webkit-animation: grow 2s infinite ease-in-out; - animation: grow 2s infinite ease-in-out; -} -.poke-final-score-number { - font-size: 8rem; - line-height: 0.4; - color: #fa9f9b; -} - -.poke-classic .poke-image-img { - -ms-interpolation-mode: nearest-neighbor; - image-rendering: -moz-crisp-edges; - image-rendering: pixelated; -} - -.animate-section-enter-active, -.animate-section-leave-active { - transition: 0.4s ease-in-out; -} -.animate-section-enter, -.animate-section-leave-to { - opacity: 0; -} -.animate-section-enter .poke-final-score-number { - transform: translateY(-30px); -} -.animate-section-leave-active { - transform: translateX(-30%); -} -.animate-section-enter-active { - transition-delay: 0.1s; - position: absolute; - top: 0; - left: 50%; - transform: translateX(-50%); -} - -.animate-options-enter-active { - transition: 0.4s ease-in-out; -} -.animate-options-enter-active:nth-child(4) { - transition-delay: 0s; -} -.animate-options-enter-active:nth-child(5) { - transition-delay: 0.2s; -} -.animate-options-enter-active:nth-child(6) { - transition-delay: 0.4s; -} -.animate-options-enter-active:nth-child(7) { - transition-delay: 0.6s; -} -.animate-options-enter-active:nth-child(8) { - transition-delay: 0.8s; -} -.animate-options-enter { - transform: rotateX(-45deg); - transform-origin: top center; - opacity: 0; -} -.animate-options-leave-active { - position: absolute; - z-index: -1; - transition: 0.8s ease-in-out; -} -.animate-options-leave-active[data-index="0"] { - top: 0; -} -.animate-options-leave-active[data-index="1"] { - top: 51px; -} -.animate-options-leave-active[data-index="2"] { - top: 102px; -} -.animate-options-leave-active[data-index="3"] { - top: 153px; -} -.animate-options-leave-to { - opacity: 0; -} - -@-webkit-keyframes grow { - 0%, - 100% { - transform: translate(-50%, -50%) scale(1); - } - 50% { - transform: translate(-50%, -50%) scale(0.6); - } -} - -@keyframes grow { - 0%, - 100% { - transform: translate(-50%, -50%) scale(1); - } - 50% { - transform: translate(-50%, -50%) scale(0.6); - } -} diff --git a/src/routes/quiz/+layout.svelte b/src/routes/quiz/+layout.svelte index a6ff40271f805507ac8fdd530b929fc4fbf8b3ee..1696c3641cfa8b73eb840350c42db64ab8489c74 100644 --- a/src/routes/quiz/+layout.svelte +++ b/src/routes/quiz/+layout.svelte @@ -6,9 +6,13 @@ .join(";"); </script> +<svelte:head> + <!-- https://stackoverflow.com/a/59165405 --> + {@html "<" + `style> :root {${cssVarStyles}}</style>`} +</svelte:head> + <div - style={cssVarStyles} - class="flex min-h-screen flex-col bg-random-500 font-game text-zinc-800" + class="flex min-h-screen flex-col font-game text-zinc-800" > <slot /> </div> diff --git a/src/routes/quiz/game-over/+page.svelte b/src/routes/quiz/game-over/+page.svelte index 6faebae70ddc265c62be59d2df3b57828e508a20..3230b1c17e0d8a8e834132340cf3576cd89bfd9d 100644 --- a/src/routes/quiz/game-over/+page.svelte +++ b/src/routes/quiz/game-over/+page.svelte @@ -27,14 +27,6 @@ </div> <style> - :global(body) { - background-color: #f65a52; - font-family: "Londrina Solid", monospace; - font-size: 16px; - line-height: 1.875em; - color: #333; - } - @keyframes -global-grow { 0%, 100% {