Frontend: Cleaning out slideshow and making it more usable and simplier. Deleted unused css. Added writables.

This commit is contained in:
Yohan Boujon 2023-11-18 00:11:36 +01:00
parent 4406c3a9a8
commit dc6d1af0d9
9 changed files with 192 additions and 308 deletions

View file

@ -1,7 +1,7 @@
<script>
import SvgIcon from "@jamescoyle/svelte-icon";
import { mdiMapMarker, mdiCog } from "@mdi/js";
import "$lib/css/education.css";
import "$lib/css/slide.css";
import { formatYear } from "$lib/js/date.js"
export let active = false;
@ -16,36 +16,36 @@
const start_year = data.start_year === null ? '' : (data.end_year === null ? formatYear(data.start_year) : '-'+formatYear(data.start_year));
</script>
<div class="education-container">
<div class="education-main {active ? '' : 'education-unactive'}">
<div class="education-img-container">
<img class="education-img" src={picture} alt="Education" />
<div class="slide-container">
<div class="slide-main {active ? '' : 'slide-unactive'}">
<div class="slide-img-container">
<img class="slide-img" src={picture} alt="Education" />
</div>
<div class="education-text-container">
<h1 class="education-title">{title}</h1>
<div class="slide-text-container">
<h1 class="slide-title">{title}</h1>
{#if location}
<div class="education-subtitle-container">
<div class="slide-subtitle-container">
<SvgIcon size="35" path={mdiMapMarker} type="mdi" />
<p class="education-subtitle education-aftericon">
<p class="slide-subtitle slide-aftericon">
{location}
</p>
</div>
{/if}
{#if speciality}
<div class="education-subtitle-container">
<div class="slide-subtitle-container">
<SvgIcon size="35" path={mdiCog} type="mdi" />
<p class="education-subtitle education-aftericon">
<p class="slide-subtitle slide-aftericon">
{speciality}
</p>
</div>
{/if}
{#if option}
<p class="education-subtitle">{option}</p>
<p class="slide-subtitle">{option}</p>
{/if}
</div>
</div>
<div class="education-time">
<div class="education-bubble" />
<h2 class="education-date">{`${end_year}${start_year}`}</h2>
<div class="slide-time">
<div class="slide-bubble" />
<h2 class="slide-date">{`${end_year}${start_year}`}</h2>
</div>
</div>

View file

@ -1,7 +1,7 @@
<script>
import SvgIcon from "@jamescoyle/svelte-icon";
import { mdiMapMarker, mdiCardText, mdiOfficeBuilding } from "@mdi/js";
import "$lib/css/experience.css";
import { mdiMapMarker, mdiOfficeBuilding } from "@mdi/js";
import "$lib/css/slide.css";
import { formatDate } from "$lib/js/date.js";
export let active = false;
@ -21,38 +21,38 @@
const picture = data.picture_url;
</script>
<div class="experience-container">
<div class="experience-main {active ? '' : 'experience-unactive'}">
<div class="experience-img-container">
<img class="experience-img" src={picture} alt="Experience" />
<div class="slide-container">
<div class="slide-main {active ? '' : 'slide-unactive'}">
<div class="slide-img-container">
<img class="slide-img" src={picture} alt="Experience" />
</div>
<div class="experience-text-container">
<h1 class="experience-title">{position}</h1>
<div class="experience-subtitle-container">
<div class="slide-text-container">
<h1 class="slide-title">{position}</h1>
<div class="slide-subtitle-container">
<SvgIcon size="35" path={mdiOfficeBuilding} type="mdi" />
<p class="experience-subtitle experience-aftericon">
<p class="slide-subtitle slide-aftericon">
{enterprise}
</p>
</div>
{#if location}
<div class="experience-subtitle-container">
<div class="slide-subtitle-container">
<SvgIcon size="35" path={mdiMapMarker} type="mdi" />
<p class="experience-subtitle experience-aftericon">
<p class="slide-subtitle slide-aftericon">
{location}
</p>
</div>
{/if}
{#if description}
<div class="experience-subtitle-container">
<p class="experience-subtitle">
<div class="slide-subtitle-container">
<p class="slide-subtitle">
{description}
</p>
</div>
{/if}
</div>
</div>
<div class="experience-time">
<div class="experience-bubble" />
<h2 class="experience-date">{`${end_year}${start_year}`}</h2>
<div class="slide-time">
<div class="slide-bubble" />
<h2 class="slide-date">{`${end_year}${start_year}`}</h2>
</div>
</div>

View file

@ -1,7 +1,7 @@
<script>
import SvgIcon from "@jamescoyle/svelte-icon";
import { mdiCalendarRange, mdiPlus } from "@mdi/js";
import "$lib/css/projects.css";
import "$lib/css/slide.css";
export let active = false;
export let data;
@ -12,26 +12,26 @@
const picture = data.picture_url;
</script>
<div class="projects-container">
<div class="projects-main {active ? '' : 'projects-unactive'}">
<div class="projects-img-container">
<img class="projects-img" src={picture} alt="projects" />
<div class="slide-container">
<div class="slide-main {active ? '' : 'slide-unactive'}">
<div class="slide-img-container">
<img class="slide-img" src={picture} alt="projects" />
</div>
<div class="projects-text-container">
<h1 class="projects-title">{title}</h1>
<div class="projects-subtitle-container">
<div class="slide-text-container">
<h1 class="slide-title">{title}</h1>
<div class="slide-subtitle-container">
<SvgIcon size="35" path={mdiCalendarRange} type="mdi" />
<p class="projects-subtitle projects-aftericon">
<p class="slide-subtitle slide-aftericon">
{issued_date}
</p>
</div>
<div class="projects-subtitle-container">
<p class="projects-subtitle projects-text">
<div class="slide-subtitle-container">
<p class="slide-subtitle slide-text">
{description}
</p>
</div>
<div class="projects-button-container">
<button class="projects-more-button">
<div class="slide-button-container">
<button class="slide-button">
<SvgIcon size="20" path={mdiPlus} type="mdi" />
More</button
>

View file

@ -3,45 +3,84 @@
import { mdiArrowRight, mdiChevronLeft } from "@mdi/js";
import "$lib/css/slideshow.css";
import { onMount } from "svelte";
import { createTimeLine } from "$lib/js/timeline.js";
import {
createTimeLine,
slideContainerCount,
slideTimelineCount,
slideStringCount,
} from "$lib/js/slideshow.js";
// Exported values
export let data = [];
export let type;
export let typename;
export let timeline = false;
// Slideshow global variables
let slideshow_index = 0;
let slideshow_hidden = [];
let slideshowTimeline;
let slideshowElements;
// Timeline global variables
let slideshow;
let bubbles = [];
if (timeline) {
onMount(() => {
for (const element of document.getElementsByClassName(
`${typename}-bubble`
)) {
onMount(() => {
/* Slideshow */
//global writer count
const currentSlideCount = $slideContainerCount;
// Sliced array from currentSlideCount to data.length
slideshowElements = Array.from(
document.querySelectorAll(".slide-container")
).slice(currentSlideCount, currentSlideCount + data.length);
// Updating with the current length
slideContainerCount.update((value) => {
return value + data.length;
});
if (timeline) {
/* SlideTimeline */
//global writer count
const currentTimelineCount = $slideTimelineCount;
// Creating the string between the bubbles
const slideshowBubbles = Array.from(
document.querySelectorAll(".slide-bubble")
).slice(currentTimelineCount, currentTimelineCount + data.length);
// Creating strings
for (const element of slideshowBubbles) {
bubbles.push({
left: element.offsetLeft,
top: element.offsetTop,
});
}
for (const div of createTimeLine(bubbles, typename)) {
const stringTimelineElements = createTimeLine(bubbles);
for (const div of stringTimelineElements) {
slideshow.appendChild(div);
}
});
}
// Updating with the current length
slideTimelineCount.update((value) => {
return value + data.length;
});
//global writer count
const currentStringCount = $slideStringCount;
// Sliced array from currentTimelineCount to data.length
slideshowTimeline = Array.from(
document.querySelectorAll(".slide-string")
).slice(
currentStringCount,
currentStringCount + stringTimelineElements.length
);
// Updating with the current length
slideStringCount.update((value) => {
return value + stringTimelineElements.length;
});
}
});
function slideCards() {
const slideshowElements = document.querySelectorAll(
`.${typename}-container`
);
const slideshowTimeline = document.querySelectorAll(
`.${typename}-string`
);
// Set or reset slideshow index, hidden array and timeling.
if (slideshow_index >= data.length - 1) {
slideshow_hidden = [];
slideshow_index = 0;
@ -54,30 +93,41 @@
slideshow_hidden.push(slideshow_index);
slideshow_index++;
}
// Incrementing the transformValue for each element
let transformValue = 0;
for (const id of slideshow_hidden) {
transformValue += slideshowElements[id].clientWidth;
}
// Translating elements
console.log(slideshowTimeline)
slideshowElements.forEach((element, id) => {
/* Slideshow translating*/
let newtransformValue = transformValue;
if (slideshow_hidden.includes(id)) {
// 1.1 because when in 'unactive' state, the scale is 0.9, adjusting the actual ratio
newtransformValue *= 1.1;
}
element.style.transform = `translateX(-${newtransformValue}px)`;
if (slideshowTimeline[id] != undefined) {
slideshowTimeline[
id
].style.transform = `translateX(-${transformValue}px)`;
if (slideshow_hidden.includes(id)) {
slideshowTimeline[id].style.backgroundColor =
"var(--color-background)";
/* Slideshow Timeline trnaslating */
if (timeline) {
if (slideshowTimeline[id] != undefined) {
slideshowTimeline[
id
].style.transform = `translateX(-${transformValue}px)`;
if (slideshow_hidden.includes(id)) {
slideshowTimeline[id].style.backgroundColor =
"var(--color-background)";
}
}
}
});
}
</script>
{@debug slideContainerCount}
<div class="slideshow" bind:this={slideshow}>
<button class="slideshow_btn" on:click={slideCards}>
<div>

View file

@ -1,103 +0,0 @@
.education-container {
display: flex;
flex-direction: column;
transition: all .3s ease 0s;
}
.education-main {
display: flex;
border-radius: 0.4rem;
box-shadow: 0px 20px 50px -10px rgba(0, 0, 0, 0.2);
background-color: var(--color-background);
height: 20rem;
margin-left: 2.5rem;
margin-right: 2.5rem;
z-index: 1;
transition: all .3s ease 0s;
}
.education-img-container{
display: flex;
margin: 1.5rem;
justify-content: center;
align-items: center;
}
.education-img {
max-height: 15rem;
min-width: 20rem;
max-width: 25rem;
}
.education-text-container {
margin: 1.5rem;
width: 25rem;
}
.education-title {
color: var(--color-text);
font-family: 'Gabarito', sans-serif;
font-weight: 600;
font-size: 2rem;
}
.education-subtitle-container {
display: flex;
flex-direction: row;
align-items: center;
}
.education-aftericon {
margin-left: 0.5rem;
}
.education-subtitle {
color: var(--color-text);
font-family: 'Gabarito', sans-serif;
font-weight: 500;
font-size: 1.5rem;
margin-top: 0.75rem;
margin-bottom: 0.75rem;
}
.education-unactive {
scale: 0.9;
margin-left: 2.25rem !important;
margin-right: 2.25rem !important;
box-shadow: 0 7px 30px -10px rgba(150,170,180,0.5) !important;
}
.education-time {
margin-top: 3rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.education-bubble {
z-index: 2;
width: 5rem;
height: 5rem;
background-color: var(--color-special);
box-shadow: 0px 2px 5px -1px rgba(0, 0, 0, 0.2);
border-radius: 50%;
transition: all .3s ease 0s;
display: flex;
justify-content: center;
align-items: center;
}
.education-date {
color: var(--color-special);
font-weight: 700;
}
.education-string {
z-index: -1;
position: absolute;
height: 3rem;
background-color: var(--color-special);
opacity: 0.5;
transition: all .3s ease 0s;
}

View file

@ -1,105 +0,0 @@
.experience-container {
display: flex;
flex-direction: column;
transition: all .3s ease 0s;
}
.experience-main {
display: flex;
border-radius: 0.4rem;
box-shadow: 0px 20px 50px -10px rgba(0, 0, 0, 0.2);
background-color: var(--color-background);
height: 22rem;
margin-left: 2.5rem;
margin-right: 2.5rem;
z-index: 1;
transition: all .3s ease 0s;
}
.experience-img-container{
display: flex;
margin: 1.5rem;
justify-content: center;
align-items: center;
}
.experience-img {
max-height: 15rem;
min-width: 20rem;
max-width: 25rem;
}
.experience-text-container {
margin: 1.5rem;
width: 25rem;
}
.experience-title {
color: var(--color-text);
font-family: 'Gabarito', sans-serif;
font-weight: 600;
font-size: 2rem;
}
.experience-subtitle-container {
display: flex;
flex-direction: row;
align-items: center;
}
.experience-aftericon {
margin-left: 0.5rem;
}
.experience-subtitle {
color: var(--color-text);
font-family: 'Gabarito', sans-serif;
font-weight: 500;
font-size: 1.5rem;
margin-top: 0.75rem;
margin-bottom: 0.75rem;
text-align:justify;
text-justify: auto;
}
.experience-unactive {
scale: 0.9;
margin-left: 2.25rem !important;
margin-right: 2.25rem !important;
box-shadow: 0 7px 30px -10px rgba(150,170,180,0.5) !important;
}
.experience-time {
margin-top: 3rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.experience-bubble {
z-index: 2;
width: 5rem;
height: 5rem;
background-color: var(--color-special);
box-shadow: 0px 2px 5px -1px rgba(0, 0, 0, 0.2);
border-radius: 50%;
transition: all .3s ease 0s;
display: flex;
justify-content: center;
align-items: center;
}
.experience-date {
color: var(--color-special);
font-weight: 700;
}
.experience-string {
z-index: -1;
position: absolute;
height: 3rem;
background-color: var(--color-special);
opacity: 0.5;
transition: all .3s ease 0s;
}

View file

@ -1,10 +1,10 @@
.projects-container {
.slide-container {
display: flex;
flex-direction: column;
transition: all .3s ease 0s;
}
.projects-main {
.slide-main {
display: flex;
border-radius: 0.4rem;
box-shadow: 0px 20px 50px -10px rgba(0, 0, 0, 0.2);
@ -16,42 +16,51 @@
transition: all .3s ease 0s;
}
.projects-img-container {
.slide-unactive {
scale: 0.9;
margin-left: 2.25rem !important;
margin-right: 2.25rem !important;
box-shadow: 0 7px 30px -10px rgba(150,170,180,0.5) !important;
}
.slide-img-container{
display: flex;
margin: 1.5rem;
justify-content: center;
align-items: center;
}
.projects-img {
.slide-img {
max-height: 15rem;
min-width: 20rem;
max-width: 25rem;
}
.projects-text-container {
.slide-text-container {
margin: 1.5rem;
width: 25rem;
}
.projects-title {
.slide-title {
color: var(--color-text);
font-family: 'Gabarito', sans-serif;
font-weight: 600;
font-size: 2rem;
}
.projects-subtitle-container {
.slide-subtitle-container {
display: flex;
flex-direction: row;
align-items: center;
}
.projects-aftericon {
/* When an icon is put after a subtitle*/
.slide-aftericon {
margin-left: 0.5rem;
}
.projects-subtitle {
/* Any Subtitle */
.slide-subtitle {
color: var(--color-text);
font-family: 'Gabarito', sans-serif;
font-weight: 500;
@ -63,7 +72,8 @@
text-justify: auto;
}
.projects-text {
/* Add it to any text that may overflow. (long texts)*/
.slide-text {
font-size: 1.25rem !important;
overflow: hidden;
display: -webkit-box;
@ -72,19 +82,14 @@
text-overflow: ellipsis;
}
.projects-unactive {
scale: 0.9;
margin-left: 2.25rem !important;
margin-right: 2.25rem !important;
box-shadow: 0 7px 30px -10px rgba(150, 170, 180, 0.5) !important;
}
.projects-button-container {
/* For button at the end of the container*/
.slide-button-container {
display: flex;
justify-content: flex-end;
}
.projects-more-button {
/* Every button are centered to the right side of the component */
.slide-button {
padding-right: 1rem;
padding-left: 1rem;
padding-top: 0.5rem;
@ -103,7 +108,7 @@
transition: all .3s ease 0s;
}
.projects-more-button:hover {
.slide-button:hover {
color: var(--color-special);
background-color: var(--color-background);
box-shadow: 0 0.7px 3px -1px rgba(150,170,180,0.5);
@ -111,7 +116,44 @@
border-color: var(--color-special);
}
.projects-more-button:active {
.slide-button:active {
transform: translateY(0.25rem);
background-color: var(--color-subtitle);
}
/* Timeline stuff */
.slide-time {
margin-top: 3rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.slide-bubble {
z-index: 2;
width: 5rem;
height: 5rem;
background-color: var(--color-special);
box-shadow: 0px 2px 5px -1px rgba(0, 0, 0, 0.2);
border-radius: 50%;
transition: all .3s ease 0s;
display: flex;
justify-content: center;
align-items: center;
}
/* Date text */
.slide-date {
color: var(--color-special);
font-weight: 700;
}
.slide-string {
z-index: -1;
position: absolute;
height: 3rem;
background-color: var(--color-special);
opacity: 0.5;
transition: all .3s ease 0s;
}

View file

@ -1,8 +1,10 @@
export function createTimeLine(positionsArray, typename) {
import { writable } from 'svelte/store';
export function createTimeLine(positionsArray) {
let divArray = [];
for (let i = 0; i < positionsArray.length - 1; i++) {
var newDiv = document.createElement('div');
newDiv.className = `${typename}-string`;
newDiv.className = "slide-string";
const left = positionsArray[i].left + (2.5 * 16);
newDiv.style.left = `${left}px`;
const top = positionsArray[i].top + 16;
@ -12,4 +14,8 @@ export function createTimeLine(positionsArray, typename) {
divArray.push(newDiv);
}
return divArray;
}
}
export let slideContainerCount = writable(0);
export let slideTimelineCount = writable(0);
export let slideStringCount = writable(0);

View file

@ -34,10 +34,8 @@
let sidebar_height = 0;
$: scrollY = 0;
$: innerHeight = 0;
$: outerHeight = 0;
onMount(() => {
sidebar_height = sidebar.offsetHeight;
console.log(sidebar_height);
sidebarScrollingHandler();
});
@ -53,7 +51,7 @@
}
</script>
<svelte:window bind:scrollY bind:innerHeight bind:outerHeight on:scroll={sidebarScrollingHandler} />
<svelte:window bind:scrollY bind:innerHeight on:scroll={sidebarScrollingHandler} />
{#if data.status == 0}
<div class="container-cv">
@ -95,22 +93,18 @@
<SlideShow
data={cv.education}
type={Education}
typename="education"
timeline="true"
/>
<Section icon={mdiBriefcase} title="Experience" />
<SlideShow
data={cv.experiences}
type={Experience}
typename="experience"
timeline="true"
/>
<Section icon={mdiWrench} title="Projects" />
<SlideShow
data={cv.projects}
type={Projects}
typename="projects"
timeline="false"
/>
<Section icon={mdiPencil} title="Skills" />
</div>