Page Loading Spinner added and Animations removal
This commit is contained in:
parent
908dc90118
commit
94e9b8f0ba
7 changed files with 227 additions and 90 deletions
78
src/lib/components/LoadingSpinner.svelte
Normal file
78
src/lib/components/LoadingSpinner.svelte
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { Circle2Types } from '../types/spinner';
|
||||||
|
export let size: Circle2Types['size'] = '60';
|
||||||
|
export let unit: Circle2Types['unit'] = 'px';
|
||||||
|
export let pause: Circle2Types['pause'] = false;
|
||||||
|
export let colorOuter: Circle2Types['colorOuter'] = '#FF3E00';
|
||||||
|
export let colorCenter: Circle2Types['colorCenter'] = '#40B3FF';
|
||||||
|
export let colorInner: Circle2Types['colorInner'] = '#676778';
|
||||||
|
export let durationMultiplier: Circle2Types['durationMultiplier'] = 1;
|
||||||
|
export let durationOuter: Circle2Types['durationOuter'] = `${durationMultiplier * 2}s`;
|
||||||
|
export let durationInner: Circle2Types['durationInner'] = `${durationMultiplier * 1.5}s`;
|
||||||
|
export let durationCenter: Circle2Types['durationCenter'] = `${durationMultiplier * 3}s`;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="circle"
|
||||||
|
class:pause-animation={pause}
|
||||||
|
style="--size: {size}{unit}; --colorInner: {colorInner}; --colorCenter: {colorCenter}; --colorOuter: {colorOuter}; --durationInner: {durationInner}; --durationCenter: {durationCenter}; --durationOuter: {durationOuter};"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.circle {
|
||||||
|
width: var(--size);
|
||||||
|
height: var(--size);
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-top-color: var(--color-active-1);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: circleSpin var(--durationOuter) linear infinite;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top:0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
.circle::before,
|
||||||
|
.circle::after {
|
||||||
|
content: '';
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.circle::after {
|
||||||
|
border-top-color: var(--color-active-2);
|
||||||
|
top: 9px;
|
||||||
|
left: 9px;
|
||||||
|
right: 9px;
|
||||||
|
bottom: 9px;
|
||||||
|
animation: circleSpin var(--durationInner) linear infinite;
|
||||||
|
}
|
||||||
|
.circle::before {
|
||||||
|
border-top-color: var(--color-text);
|
||||||
|
top: 3px;
|
||||||
|
left: 3px;
|
||||||
|
right: 3px;
|
||||||
|
bottom: 3px;
|
||||||
|
animation: circleSpin var(--durationCenter) linear infinite;
|
||||||
|
}
|
||||||
|
.pause-animation,
|
||||||
|
.pause-animation::after,
|
||||||
|
.pause-animation::before {
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes circleSpin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
17
src/lib/types/spinner.ts
Normal file
17
src/lib/types/spinner.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
export type SpinnerTypes = {
|
||||||
|
size: string | number;
|
||||||
|
color: string;
|
||||||
|
unit: string;
|
||||||
|
duration: string;
|
||||||
|
pause: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Circle2Types = {
|
||||||
|
colorOuter: string;
|
||||||
|
colorCenter: string;
|
||||||
|
colorInner: string;
|
||||||
|
durationMultiplier: number;
|
||||||
|
durationOuter: string;
|
||||||
|
durationInner: string;
|
||||||
|
durationCenter: string;
|
||||||
|
} & SpinnerTypes;
|
|
@ -14,6 +14,7 @@
|
||||||
import type { LayoutData } from '../$types';
|
import type { LayoutData } from '../$types';
|
||||||
import type { Ethic } from '$lib/types/stellaris';
|
import type { Ethic } from '$lib/types/stellaris';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
|
import LoadingSpinner from '$lib/components/LoadingSpinner.svelte';
|
||||||
|
|
||||||
export let data: LayoutData;
|
export let data: LayoutData;
|
||||||
let selectedGameGroups: Array<number> = [];
|
let selectedGameGroups: Array<number> = [];
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
let selectedGameIdx: number;
|
let selectedGameIdx: number;
|
||||||
let selectedGame: ChellarisGame = createChellarisGame();
|
let selectedGame: ChellarisGame = createChellarisGame();
|
||||||
let pageData: {
|
let pageData: {
|
||||||
|
init: boolean;
|
||||||
empireCount: number;
|
empireCount: number;
|
||||||
gestaltCount: { total: number; machines: number };
|
gestaltCount: { total: number; machines: number };
|
||||||
ethicsData: Map<
|
ethicsData: Map<
|
||||||
|
@ -36,10 +38,11 @@
|
||||||
>;
|
>;
|
||||||
takenPortraits: Map<number, Map<number, number>>;
|
takenPortraits: Map<number, Map<number, number>>;
|
||||||
} = {
|
} = {
|
||||||
|
init: false,
|
||||||
empireCount: 0,
|
empireCount: 0,
|
||||||
gestaltCount: { total: 0, machines: 0 },
|
gestaltCount: { total: 0, machines: 0 },
|
||||||
ethicsData: new Map(),
|
ethicsData: new Map(),
|
||||||
takenPortraits: new Map(),
|
takenPortraits: new Map()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save Tab to Store
|
// Save Tab to Store
|
||||||
|
@ -141,14 +144,14 @@
|
||||||
}
|
}
|
||||||
const portraitGroupData = pageData.takenPortraits.get(empire.empire_portrait_group);
|
const portraitGroupData = pageData.takenPortraits.get(empire.empire_portrait_group);
|
||||||
|
|
||||||
if (typeof portraitGroupData !== "undefined") {
|
if (typeof portraitGroupData !== 'undefined') {
|
||||||
if (!portraitGroupData.has(empire.empire_portrait)) {
|
if (!portraitGroupData.has(empire.empire_portrait)) {
|
||||||
portraitGroupData.set(empire.empire_portrait, 0);
|
portraitGroupData.set(empire.empire_portrait, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let portraitData = portraitGroupData.get(empire.empire_portrait);
|
let portraitData = portraitGroupData.get(empire.empire_portrait);
|
||||||
|
|
||||||
if (typeof portraitData !== "undefined") {
|
if (typeof portraitData !== 'undefined') {
|
||||||
portraitData = portraitData + 1;
|
portraitData = portraitData + 1;
|
||||||
portraitGroupData.set(empire.empire_portrait, portraitData);
|
portraitGroupData.set(empire.empire_portrait, portraitData);
|
||||||
pageData.takenPortraits.set(empire.empire_portrait_group, portraitGroupData);
|
pageData.takenPortraits.set(empire.empire_portrait_group, portraitGroupData);
|
||||||
|
@ -157,6 +160,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
pageData.empireCount = groupEmpires.size;
|
pageData.empireCount = groupEmpires.size;
|
||||||
|
pageData.init = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -204,6 +208,7 @@
|
||||||
<meta name="description" content="Chellaris Sign-Up Graphs" />
|
<meta name="description" content="Chellaris Sign-Up Graphs" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
|
{#if pageData.init}
|
||||||
<h1>
|
<h1>
|
||||||
{selectedGame.name} Sign-Up Info for {groupNoun}
|
{selectedGame.name} Sign-Up Info for {groupNoun}
|
||||||
{selectedGameGroups.map((selection) => gameGroups.get(selection)?.name).join(groupJoiner)}
|
{selectedGameGroups.map((selection) => gameGroups.get(selection)?.name).join(groupJoiner)}
|
||||||
|
@ -265,11 +270,30 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{portraitGroup[1].displayName}</td>
|
<td>{portraitGroup[1].displayName}</td>
|
||||||
{#each portraitGroup[1].portraits as portrait}
|
{#each portraitGroup[1].portraits as portrait}
|
||||||
<td class="image-box" style="--color-hovered-portrait: {
|
<td
|
||||||
(gameGroups.size - 1) - (pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) == 0 ? "var(--color-warn-2)" :
|
class="image-box"
|
||||||
(gameGroups.size - 1) - (pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) != (gameGroups.size - 1) ? "var(--color-warn-1)" : "var(--color-bg)"}">
|
style="--color-hovered-portrait: {gameGroups.size -
|
||||||
<input id={portraitGroup[0] + "-" + portrait[0]} type="image" src={portrait[1].imageLink} alt={portraitGroup[1].displayName + "-" + portrait[0]}>
|
1 -
|
||||||
<label for={portraitGroup[0] + "-" + portrait[0]}>{pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0}/{gameGroups.size - 1}</label>
|
(pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) ==
|
||||||
|
0
|
||||||
|
? 'var(--color-warn-2)'
|
||||||
|
: gameGroups.size -
|
||||||
|
1 -
|
||||||
|
(pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) !=
|
||||||
|
gameGroups.size - 1
|
||||||
|
? 'var(--color-warn-1)'
|
||||||
|
: 'var(--color-bg)'}"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id={portraitGroup[0] + '-' + portrait[0]}
|
||||||
|
type="image"
|
||||||
|
src={"../"+ portrait[1].lores}
|
||||||
|
alt={portraitGroup[1].displayName + '-' + portrait[0]}
|
||||||
|
/>
|
||||||
|
<label for={portraitGroup[0] + '-' + portrait[0]}
|
||||||
|
>{pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) ||
|
||||||
|
0}/{gameGroups.size - 1}</label
|
||||||
|
>
|
||||||
</td>
|
</td>
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -278,6 +302,9 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
{:else}
|
||||||
|
<LoadingSpinner size="60" />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
th,
|
th,
|
||||||
|
@ -353,5 +380,4 @@
|
||||||
transition-duration: 0.1s;
|
transition-duration: 0.1s;
|
||||||
transition-timing-function: linear;
|
transition-timing-function: linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
import EthicsBar from './EthicsBar.svelte';
|
import EthicsBar from './EthicsBar.svelte';
|
||||||
import PopsPie from './PopsPie.svelte';
|
import PopsPie from './PopsPie.svelte';
|
||||||
import EmpireStats from './EmpireStats.svelte';
|
import EmpireStats from './EmpireStats.svelte';
|
||||||
|
import LoadingSpinner from '$lib/components/LoadingSpinner.svelte';
|
||||||
|
import { navigating } from '$app/stores';
|
||||||
|
import { fade } from 'svelte/transition';
|
||||||
|
|
||||||
export let data: {
|
export let data: {
|
||||||
popsData: Array<number>;
|
popsData: Array<number>;
|
||||||
|
@ -16,6 +19,9 @@
|
||||||
<meta name="description" content="Graphs for Chellaris Game 15" />
|
<meta name="description" content="Graphs for Chellaris Game 15" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
|
{#if $navigating}
|
||||||
|
<LoadingSpinner size="60" />
|
||||||
|
{:else}
|
||||||
<div class="fullscreen-margin">
|
<div class="fullscreen-margin">
|
||||||
<div class="half-vertical">
|
<div class="half-vertical">
|
||||||
<div class="two-thirds-horizontal">
|
<div class="two-thirds-horizontal">
|
||||||
|
@ -34,6 +40,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.fullscreen-margin {
|
.fullscreen-margin {
|
||||||
|
|
|
@ -61,6 +61,9 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
animation: {
|
||||||
|
duration: 0
|
||||||
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
scales: {
|
scales: {
|
||||||
y: {
|
y: {
|
||||||
|
|
|
@ -96,6 +96,9 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
animation: {
|
||||||
|
duration: 0
|
||||||
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
callbacks: {
|
callbacks: {
|
||||||
|
|
|
@ -42,6 +42,9 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
animation: {
|
||||||
|
duration: 0
|
||||||
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
callbacks: {
|
callbacks: {
|
||||||
|
|
Reference in a new issue