✨ Rework About page Process section
This commit is contained in:
25
src/animations/transitions.ts
Normal file
25
src/animations/transitions.ts
Normal 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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
{/if}
|
||||||
<div class="overlay" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -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>
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user