Rework About page Process section

This commit is contained in:
2022-09-07 22:47:00 +02:00
parent 46a78851ec
commit 351061dc61
5 changed files with 148 additions and 192 deletions

View File

@@ -0,0 +1,25 @@
import { animate } from 'motion'
import { quartOut } from './easings'
export const scaleFade = (node: HTMLElement, {
delay = 0,
duration = 1,
scale = [0.7, 1],
opacity = [1, 0],
x = null,
}) => {
return {
css: () => {
animate(node, {
scale,
opacity,
x,
z: 0,
}, {
easing: quartOut,
duration,
delay,
})
}
}
}

View File

@@ -3,21 +3,33 @@
</style> </style>
<script lang="ts"> <script lang="ts">
import { scaleFade } from '$animations/transitions'
// Components // Components
import Image from '$components/atoms/Image.svelte' import Image from '$components/atoms/Image.svelte'
import { getAssetUrlKey } from '$utils/api' import { getAssetUrlKey } from '$utils/api'
export let index: number export let index: number
export let title: string
export let text: string export let text: string
export let image: any = undefined export let image: any = undefined
export let video: any = undefined export let video: any = undefined
export let visible: boolean = false
let videoEl: HTMLVideoElement
const imageRatio = image ? image.width / image.height : undefined const imageRatio = image ? image.width / image.height : undefined
// Toggle video playback if step is visible
$: if (videoEl) {
visible ? videoEl.play() : videoEl.pause()
}
</script> </script>
<div class="step" style:--index={index}> {#if visible}
<div class="step__card grid"> <div class="step grid" style:--index={index}
in:scaleFade|local={{ scale: [1.1, 1], opacity: [0, 1], x: [20, 0], delay: 0.2 }}
out:scaleFade|local={{ scale: [1, 0.9], opacity: [1, 0], x: [0, -20] }}
>
{#if image || video} {#if image || video}
<div class="media"> <div class="media">
{#if image} {#if image}
@@ -34,7 +46,7 @@
alt={image.title} alt={image.title}
/> />
{:else if video} {:else if video}
<video muted loop playsinline allow="autoplay"> <video muted loop playsinline autoplay allow="autoplay" bind:this={videoEl}>
<source type="video/mp4" src={getAssetUrlKey(video.mp4, 'step')} /> <source type="video/mp4" src={getAssetUrlKey(video.mp4, 'step')} />
<source type="video/webm" src={getAssetUrlKey(video.webm, 'step')} /> <source type="video/webm" src={getAssetUrlKey(video.webm, 'step')} />
<track kind="captions" /> <track kind="captions" />
@@ -43,13 +55,8 @@
</div> </div>
{/if} {/if}
<div class="content">
<h3 class="title-medium">{title}</h3>
<div class="text text-small"> <div class="text text-small">
{@html text} {@html text}
</div> </div>
</div>
<div class="overlay" />
</div>
</div> </div>
{/if}

View File

@@ -3,10 +3,10 @@
</style> </style>
<script lang="ts"> <script lang="ts">
import { navigating } from '$app/stores' import { navigating, page } from '$app/stores'
import { onMount, afterUpdate } from 'svelte' import { onMount, afterUpdate } from 'svelte'
import type { PageData } from './$types' import type { PageData } from './$types'
import { scroll, animate, inView, type ScrollOptions, timeline } from 'motion' import { scroll, animate, inView, timeline } from 'motion'
import { map } from '$utils/functions' import { map } from '$utils/functions'
import { getAssetUrlKey } from '$utils/api' import { getAssetUrlKey } from '$utils/api'
import { DELAY } from '$utils/contants' import { DELAY } from '$utils/contants'
@@ -27,11 +27,12 @@
const { about, photos } = data const { about, photos } = data
let scrollY: number, innerWidth: number, innerHeight: number let scrollY: number, innerWidth: number, innerHeight: number
let purposeEl: HTMLElement, stepsEl: HTMLElement, photosGridEl: HTMLElement let purposeEl: HTMLElement, photosGridEl: HTMLElement
let currentStep: number = 0
let photoFirstEl: HTMLElement, photoUsEl: HTMLElement let photoFirstEl: HTMLElement, photoUsEl: HTMLElement
let videosObserver: IntersectionObserver
let photosGridOffset: number = photosGridEl && photosGridEl.offsetTop let photosGridOffset: number = photosGridEl && photosGridEl.offsetTop
$: currentStep = $page.url.hash ? Number($page.url.hash.split('#step-')[1]) - 1 : 0
$: parallaxPhotos = photosGridEl && map(scrollY, photosGridOffset - innerHeight, photosGridOffset + innerHeight / 1.5, 0, innerHeight * 0.15, true) $: parallaxPhotos = photosGridEl && map(scrollY, photosGridOffset - innerHeight, photosGridOffset + innerHeight / 1.5, 0, innerHeight * 0.15, true)
$: fadedPhotosIndexes = innerWidth > 768 $: fadedPhotosIndexes = innerWidth > 768
? [0, 2, 5, 7, 9, 12, 17, 20, 22, 26, 30, 32, 34] ? [0, 2, 5, 7, 9, 12, 17, 20, 22, 26, 30, 32, 34]
@@ -282,37 +283,36 @@
<section class="about__process"> <section class="about__process">
<div class="container grid"> <div class="container grid">
<div class="title"> <aside>
<h2 class="title-big">{about.process_title}</h2> <div class="heading">
<h2 class="title-medium">{about.process_title}</h2>
<p class="text-normal">{about.process_subtitle}</p> <p class="text-normal">{about.process_subtitle}</p>
</div> </div>
<div class="steps grid" bind:this={stepsEl} <ol>
style:--cards-amount={about.process_steps.length} {#each about.process_steps as { title }, index}
> <li class:is-active={index === currentStep}>
{#each about.process_steps as { title, text, image, video_mp4, video_webm }, index} <a href="#step-{index + 1}" class="title-big">
<span>{title}</span>
</a>
</li>
{/each}
</ol>
</aside>
<div class="steps">
{#each about.process_steps as { text, image, video_mp4, video_webm }, index}
<ProcessStep <ProcessStep
{index} {title} {text} {index} {text}
image={image ?? undefined} image={image ?? undefined}
video={video_mp4 && video_webm ? { video={video_mp4 && video_webm ? {
mp4: video_mp4.id, mp4: video_mp4.id,
webm: video_webm.id webm: video_webm.id
} : undefined} } : undefined}
visible={index === currentStep}
/> />
{/each} {/each}
</div> </div>
<div class="intention">
<InteractiveGlobe2
enableMarkers={false}
speed={0.005}
pane={false}
width={200}
/>
<p class="intention__content title-medium">
{about.process_intention}
</p>
</div>
</div> </div>
</section> </section>
@@ -330,10 +330,9 @@
</div> </div>
</section> </section>
<div class="about__bottom container grid">
<section class="about__interest grid"> <section class="about__interest grid">
<div class="container grid">
<h2 class="title-xl">{about.contact_title}</h2> <h2 class="title-xl">{about.contact_title}</h2>
<div class="blocks"> <div class="blocks">
{#each about.contact_blocks as { title, text, link, button }} {#each about.contact_blocks as { title, text, link, button }}
<div class="block"> <div class="block">
@@ -345,13 +344,6 @@
</div> </div>
{/each} {/each}
</div> </div>
</section>
<section class="grid-modules">
<div class="wrap">
<ShopModule />
<NewsletterModule />
</div> </div>
</section> </section>
</div>
</PageTransition> </PageTransition>

View File

@@ -1,7 +1,5 @@
// About page Step // About page Step
.step { .step {
// Card
&__card {
position: relative; position: relative;
display: block; display: block;
overflow: hidden; overflow: hidden;
@@ -11,14 +9,13 @@
transform: translateZ(0); transform: translateZ(0);
@include bp (sm) { @include bp (sm) {
--columns: 18; --columns: 11;
display: grid; display: grid;
grid-template-rows: repeat(2, 1fr); grid-template-rows: repeat(2, 1fr);
padding: 5.5% 0; padding: 8% 0;
min-height: min(45vw, 720px); min-height: clamp(400px, 75vh, 800px);
border-radius: 16px; border-radius: 16px;
} }
}
// Image // Image
.media { .media {
@@ -27,87 +24,36 @@
display: block; display: block;
overflow: hidden; overflow: hidden;
width: 70%; width: 70%;
max-height: 580px; max-height: 550px;
margin: 0 auto 64px; margin-bottom: 48px;
border-radius: 6px; border-radius: 6px;
@include bp (sm) { @include bp (sm) {
grid-column: 11 / -2; grid-column: 2 / span 6;
grid-row: 1 / -1; grid-row: 1 / -1;
width: 100%; width: 100%;
height: 100%; height: auto;
margin-bottom: 0;
} }
video, :global(.image) {
display: block;
height: 100%;
width: 100%;
object-fit: cover;
}
:global(.image) { :global(.image) {
:global(img) { // width: 100%;
// height: 100%;
}
:global(.image img), video {
display: block; display: block;
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
} }
} }
}
// Content // Content
.content { .text {
position: relative; position: relative;
z-index: 2; z-index: 2;
@include bp (sm) {
grid-column: 2 / span 7;
grid-row: 2;
align-self: flex-end;
}
h3 {
margin-bottom: 8px;
color: #fff;
@include bp (sm) {
margin-bottom: 16px;
}
}
.text {
line-height: 1.5; line-height: 1.5;
font-weight: 300; font-weight: 300;
color: $color-secondary-light; color: $color-secondary-light;
} grid-column: 2 / -2;
}
// Overlay
.overlay {
content: "";
display: block;
position: absolute;
z-index: 0;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000;
opacity: 0;
pointer-events: none;
transform: translateZ(0);
}
// Alternate content order
&:nth-child(even) {
.media {
@include bp (sm) {
grid-column: 2 / span 7;
}
}
.content {
@include bp (sm) {
grid-column: 11 / -2;
}
}
} }
} }

View File

@@ -356,10 +356,10 @@
&__photos { &__photos {
position: relative; position: relative;
z-index: 1; z-index: 1;
margin-top: -64px; // margin-top: -64px;
@include bp (sm) { @include bp (sm) {
margin-top: -120px; // margin-top: -120px;
} }
.container-wide { .container-wide {
@@ -434,27 +434,11 @@
} }
} }
/*
** Bottom
*/
&__bottom {
@include bp (sm) {
margin-top: calc(-1 * clamp(160px, 14vw, 240px));
}
// Modules
.grid-modules {
grid-column: 1 / -1;
@include bp (sm) {
grid-column: 2 / -2;
}
}
}
// Interest // Interest
&__interest { &__interest {
margin-top: calc(-1 * clamp(160px, 14vw, 256px));
& > .container {
position: relative; position: relative;
z-index: 2; z-index: 2;
display: block; display: block;
@@ -465,11 +449,13 @@
box-shadow: 0px -24px 120px rgba($color-primary-darker, 0.8); box-shadow: 0px -24px 120px rgba($color-primary-darker, 0.8);
@include bp (sm) { @include bp (sm) {
--columns: 22;
display: grid; display: grid;
grid-column: 2 / -2; grid-column: 2 / -2;
margin-bottom: 48px; margin-bottom: 64px;
padding: clamp(72px, 8vw, 160px) 0; padding: clamp(72px, 8vw, 160px) 0;
} }
}
h2 { h2 {
grid-column: 1 / -1; grid-column: 1 / -1;