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 { Ethic } from '$lib/types/stellaris';
|
||||
import { page } from '$app/stores';
|
||||
import LoadingSpinner from '$lib/components/LoadingSpinner.svelte';
|
||||
|
||||
export let data: LayoutData;
|
||||
let selectedGameGroups: Array<number> = [];
|
||||
|
@ -23,6 +24,7 @@
|
|||
let selectedGameIdx: number;
|
||||
let selectedGame: ChellarisGame = createChellarisGame();
|
||||
let pageData: {
|
||||
init: boolean;
|
||||
empireCount: number;
|
||||
gestaltCount: { total: number; machines: number };
|
||||
ethicsData: Map<
|
||||
|
@ -36,10 +38,11 @@
|
|||
>;
|
||||
takenPortraits: Map<number, Map<number, number>>;
|
||||
} = {
|
||||
init: false,
|
||||
empireCount: 0,
|
||||
gestaltCount: { total: 0, machines: 0 },
|
||||
ethicsData: new Map(),
|
||||
takenPortraits: new Map(),
|
||||
takenPortraits: new Map()
|
||||
};
|
||||
|
||||
// Save Tab to Store
|
||||
|
@ -141,14 +144,14 @@
|
|||
}
|
||||
const portraitGroupData = pageData.takenPortraits.get(empire.empire_portrait_group);
|
||||
|
||||
if (typeof portraitGroupData !== "undefined") {
|
||||
if (typeof portraitGroupData !== 'undefined') {
|
||||
if (!portraitGroupData.has(empire.empire_portrait)) {
|
||||
portraitGroupData.set(empire.empire_portrait, 0);
|
||||
}
|
||||
|
||||
let portraitData = portraitGroupData.get(empire.empire_portrait);
|
||||
|
||||
if (typeof portraitData !== "undefined") {
|
||||
if (typeof portraitData !== 'undefined') {
|
||||
portraitData = portraitData + 1;
|
||||
portraitGroupData.set(empire.empire_portrait, portraitData);
|
||||
pageData.takenPortraits.set(empire.empire_portrait_group, portraitGroupData);
|
||||
|
@ -157,6 +160,7 @@
|
|||
}
|
||||
});
|
||||
pageData.empireCount = groupEmpires.size;
|
||||
pageData.init = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -204,80 +208,103 @@
|
|||
<meta name="description" content="Chellaris Sign-Up Graphs" />
|
||||
</svelte:head>
|
||||
|
||||
<h1>
|
||||
{selectedGame.name} Sign-Up Info for {groupNoun}
|
||||
{selectedGameGroups.map((selection) => gameGroups.get(selection)?.name).join(groupJoiner)}
|
||||
</h1>
|
||||
{#if pageData.init}
|
||||
<h1>
|
||||
{selectedGame.name} Sign-Up Info for {groupNoun}
|
||||
{selectedGameGroups.map((selection) => gameGroups.get(selection)?.name).join(groupJoiner)}
|
||||
</h1>
|
||||
|
||||
<div class="text-column">
|
||||
<h4>
|
||||
Empires signed up: {pageData.empireCount}
|
||||
</h4>
|
||||
<section class="ethics-columns">
|
||||
<div class="ethics-column">
|
||||
<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}
|
||||
<div class="text-column">
|
||||
<h4>
|
||||
Empires signed up: {pageData.empireCount}
|
||||
</h4>
|
||||
<section class="ethics-columns">
|
||||
<div class="ethics-column">
|
||||
<table>
|
||||
<tr>
|
||||
<td>{portraitGroup[1].displayName}</td>
|
||||
{#each portraitGroup[1].portraits as portrait}
|
||||
<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].imageLink} 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>
|
||||
<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}
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{#each chellarisData.species as portraitGroup}
|
||||
<tr>
|
||||
<td>{portraitGroup[1].displayName}</td>
|
||||
{#each portraitGroup[1].portraits as portrait}
|
||||
<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>
|
||||
th,
|
||||
|
@ -353,5 +380,4 @@
|
|||
transition-duration: 0.1s;
|
||||
transition-timing-function: linear;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
import EthicsBar from './EthicsBar.svelte';
|
||||
import PopsPie from './PopsPie.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: {
|
||||
popsData: Array<number>;
|
||||
|
@ -16,24 +19,28 @@
|
|||
<meta name="description" content="Graphs for Chellaris Game 15" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="fullscreen-margin">
|
||||
<div class="half-vertical">
|
||||
<div class="two-thirds-horizontal">
|
||||
<EthicsWeb {data} />
|
||||
{#if $navigating}
|
||||
<LoadingSpinner size="60" />
|
||||
{:else}
|
||||
<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 class="one-third-horizontal">
|
||||
<EthicsBar {data} />
|
||||
<div class="half-vertical">
|
||||
<div class="half-horizontal">
|
||||
<EmpireStats {data} />
|
||||
</div>
|
||||
<div class="half-horizontal">
|
||||
<PopsPie {data} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="half-vertical">
|
||||
<div class="half-horizontal">
|
||||
<EmpireStats {data} />
|
||||
</div>
|
||||
<div class="half-horizontal">
|
||||
<PopsPie {data} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.fullscreen-margin {
|
||||
|
|
|
@ -61,6 +61,9 @@
|
|||
};
|
||||
|
||||
const options = {
|
||||
animation: {
|
||||
duration: 0
|
||||
},
|
||||
plugins: {
|
||||
scales: {
|
||||
y: {
|
||||
|
|
|
@ -96,6 +96,9 @@
|
|||
};
|
||||
|
||||
const options = {
|
||||
animation: {
|
||||
duration: 0
|
||||
},
|
||||
plugins: {
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
};
|
||||
|
||||
const options = {
|
||||
animation: {
|
||||
duration: 0
|
||||
},
|
||||
plugins: {
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
|
|
Reference in a new issue