Page Loading Spinner added and Animations removal

This commit is contained in:
Neshura 2023-08-21 03:45:26 +02:00
parent 908dc90118
commit 94e9b8f0ba
Signed by: Neshura
GPG key ID: B6983AAA6B9A7A6C
7 changed files with 227 additions and 90 deletions

View 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
View 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;

View file

@ -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
@ -135,20 +138,20 @@
pageData.ethicsData.set(id, newEthicsData); pageData.ethicsData.set(id, newEthicsData);
} }
}); });
if (!pageData.takenPortraits.has(empire.empire_portrait_group)) { if (!pageData.takenPortraits.has(empire.empire_portrait_group)) {
pageData.takenPortraits.set(empire.empire_portrait_group, new Map()); pageData.takenPortraits.set(empire.empire_portrait_group, new Map());
} }
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,80 +208,103 @@
<meta name="description" content="Chellaris Sign-Up Graphs" /> <meta name="description" content="Chellaris Sign-Up Graphs" />
</svelte:head> </svelte:head>
<h1> {#if pageData.init}
{selectedGame.name} Sign-Up Info for {groupNoun} <h1>
{selectedGameGroups.map((selection) => gameGroups.get(selection)?.name).join(groupJoiner)} {selectedGame.name} Sign-Up Info for {groupNoun}
</h1> {selectedGameGroups.map((selection) => gameGroups.get(selection)?.name).join(groupJoiner)}
</h1>
<div class="text-column"> <div class="text-column">
<h4> <h4>
Empires signed up: {pageData.empireCount} Empires signed up: {pageData.empireCount}
</h4> </h4>
<section class="ethics-columns"> <section class="ethics-columns">
<div class="ethics-column"> <div class="ethics-column">
<table> <table>
<tr>
<th>Ethic</th>
<th># Regular</th>
<th># Fanatic</th>
</tr>
{#each pageData.ethicsData as ethicData}
{#if !ethicData[1].machine}
<tr>
<td class="table-label">{ethicData[1].displayName}</td>
<td>{ethicData[1].regular}</td>
<td>{ethicData[1].fanatic}</td>
</tr>
{/if}
{/each}
</table>
</div>
<div class="ethics-column">
<p>Total Gestalts: {pageData.gestaltCount.total}</p>
<p>> Hive Minds: {pageData.gestaltCount.total - pageData.gestaltCount.machines}</p>
<p>> Machines: {pageData.gestaltCount.machines}</p>
<table>
<tr>
<th>Machine Ethic</th>
<th>#</th>
</tr>
{#each pageData.ethicsData as ethicData}
{#if ethicData[1].machine}
<tr>
<td class="table-label">{ethicData[1].displayName}</td>
<td>{ethicData[1].regular}</td>
</tr>
{/if}
{/each}
</table>
</div>
</section>
<section>
<div class="text-column">
<table>
<tr>
<th>Species</th>
{#each Array(18) as _, index (index)}
<th>{index + 1}</th>
{/each}
</tr>
{#each chellarisData.species as portraitGroup}
<tr> <tr>
<td>{portraitGroup[1].displayName}</td> <th>Ethic</th>
{#each portraitGroup[1].portraits as portrait} <th># Regular</th>
<td class="image-box" style="--color-hovered-portrait: { <th># Fanatic</th>
(gameGroups.size - 1) - (pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) == 0 ? "var(--color-warn-2)" : </tr>
(gameGroups.size - 1) - (pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) != (gameGroups.size - 1) ? "var(--color-warn-1)" : "var(--color-bg)"}"> {#each pageData.ethicsData as ethicData}
<input id={portraitGroup[0] + "-" + portrait[0]} type="image" src={portrait[1].imageLink} alt={portraitGroup[1].displayName + "-" + portrait[0]}> {#if !ethicData[1].machine}
<label for={portraitGroup[0] + "-" + portrait[0]}>{pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0}/{gameGroups.size - 1}</label> <tr>
</td> <td class="table-label">{ethicData[1].displayName}</td>
<td>{ethicData[1].regular}</td>
<td>{ethicData[1].fanatic}</td>
</tr>
{/if}
{/each}
</table>
</div>
<div class="ethics-column">
<p>Total Gestalts: {pageData.gestaltCount.total}</p>
<p>> Hive Minds: {pageData.gestaltCount.total - pageData.gestaltCount.machines}</p>
<p>> Machines: {pageData.gestaltCount.machines}</p>
<table>
<tr>
<th>Machine Ethic</th>
<th>#</th>
</tr>
{#each pageData.ethicsData as ethicData}
{#if ethicData[1].machine}
<tr>
<td class="table-label">{ethicData[1].displayName}</td>
<td>{ethicData[1].regular}</td>
</tr>
{/if}
{/each}
</table>
</div>
</section>
<section>
<div class="text-column">
<table>
<tr>
<th>Species</th>
{#each Array(18) as _, index (index)}
<th>{index + 1}</th>
{/each} {/each}
</tr> </tr>
{/each} {#each chellarisData.species as portraitGroup}
</table> <tr>
</div> <td>{portraitGroup[1].displayName}</td>
</section> {#each portraitGroup[1].portraits as portrait}
</div> <td
class="image-box"
style="--color-hovered-portrait: {gameGroups.size -
1 -
(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>
{/each}
</tr>
{/each}
</table>
</div>
</section>
</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>

View file

@ -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,24 +19,28 @@
<meta name="description" content="Graphs for Chellaris Game 15" /> <meta name="description" content="Graphs for Chellaris Game 15" />
</svelte:head> </svelte:head>
<div class="fullscreen-margin"> {#if $navigating}
<div class="half-vertical"> <LoadingSpinner size="60" />
<div class="two-thirds-horizontal"> {:else}
<EthicsWeb {data} /> <div class="fullscreen-margin">
<div class="half-vertical">
<div class="two-thirds-horizontal">
<EthicsWeb {data} />
</div>
<div class="one-third-horizontal">
<EthicsBar {data} />
</div>
</div> </div>
<div class="one-third-horizontal"> <div class="half-vertical">
<EthicsBar {data} /> <div class="half-horizontal">
<EmpireStats {data} />
</div>
<div class="half-horizontal">
<PopsPie {data} />
</div>
</div> </div>
</div> </div>
<div class="half-vertical"> {/if}
<div class="half-horizontal">
<EmpireStats {data} />
</div>
<div class="half-horizontal">
<PopsPie {data} />
</div>
</div>
</div>
<style> <style>
.fullscreen-margin { .fullscreen-margin {

View file

@ -61,6 +61,9 @@
}; };
const options = { const options = {
animation: {
duration: 0
},
plugins: { plugins: {
scales: { scales: {
y: { y: {

View file

@ -96,6 +96,9 @@
}; };
const options = { const options = {
animation: {
duration: 0
},
plugins: { plugins: {
tooltip: { tooltip: {
callbacks: { callbacks: {

View file

@ -42,6 +42,9 @@
}; };
const options = { const options = {
animation: {
duration: 0
},
plugins: { plugins: {
tooltip: { tooltip: {
callbacks: { callbacks: {