Create a component for scrolling huge titles
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
"lint": "eslint --ignore-path .gitignore ."
|
||||
},
|
||||
"dependencies": {
|
||||
"animejs": "^3.2.1",
|
||||
"dayjs": "^1.10.7",
|
||||
"embla-carousel": "^5.0.1",
|
||||
"focus-visible": "^5.2.0",
|
||||
@@ -26,6 +27,7 @@
|
||||
"@sveltejs/adapter-node": "next",
|
||||
"@sveltejs/adapter-vercel": "next",
|
||||
"@sveltejs/kit": "next",
|
||||
"@types/animejs": "^3.1.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.3.1",
|
||||
"@typescript-eslint/parser": "^5.3.1",
|
||||
"eslint": "^8.2.0",
|
||||
|
||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -4,8 +4,10 @@ specifiers:
|
||||
'@sveltejs/adapter-node': next
|
||||
'@sveltejs/adapter-vercel': next
|
||||
'@sveltejs/kit': next
|
||||
'@types/animejs': ^3.1.4
|
||||
'@typescript-eslint/eslint-plugin': ^5.3.1
|
||||
'@typescript-eslint/parser': ^5.3.1
|
||||
animejs: ^3.2.1
|
||||
dayjs: ^1.10.7
|
||||
embla-carousel: ^5.0.1
|
||||
eslint: ^8.2.0
|
||||
@@ -21,6 +23,7 @@ specifiers:
|
||||
typescript: ^4.4.4
|
||||
|
||||
dependencies:
|
||||
animejs: 3.2.1
|
||||
dayjs: 1.10.7
|
||||
embla-carousel: 5.0.1
|
||||
focus-visible: 5.2.0
|
||||
@@ -30,6 +33,7 @@ devDependencies:
|
||||
'@sveltejs/adapter-node': 1.0.0-next.55
|
||||
'@sveltejs/adapter-vercel': 1.0.0-next.31
|
||||
'@sveltejs/kit': 1.0.0-next.196_sass@1.43.4+svelte@3.44.1
|
||||
'@types/animejs': 3.1.4
|
||||
'@typescript-eslint/eslint-plugin': 5.3.1_4653b7803b7453f5f37717b7e1448517
|
||||
'@typescript-eslint/parser': 5.3.1_eslint@8.2.0+typescript@4.4.4
|
||||
eslint: 8.2.0
|
||||
@@ -161,6 +165,10 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@types/animejs/3.1.4:
|
||||
resolution: {integrity: sha512-WUjeFT2SXd6intfE6cg6eL1jk/JL88JqM2gC4WqO4iHLmbCvHUq6aoLK13lGpDWs4FtS2PHoYraJZ0dEx99Dyg==}
|
||||
dev: true
|
||||
|
||||
/@types/json-schema/7.0.9:
|
||||
resolution: {integrity: sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==}
|
||||
dev: true
|
||||
@@ -308,6 +316,10 @@ packages:
|
||||
uri-js: 4.4.1
|
||||
dev: true
|
||||
|
||||
/animejs/3.2.1:
|
||||
resolution: {integrity: sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A==}
|
||||
dev: false
|
||||
|
||||
/ansi-colors/4.1.1:
|
||||
resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
@@ -35,4 +35,11 @@
|
||||
{/each}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{:else}
|
||||
<span class={classes}>
|
||||
{#each split as char, i}
|
||||
<span class="char" style="--i-c: {i};">{char}</span>
|
||||
{/each}
|
||||
</span>
|
||||
{/if}
|
||||
41
src/components/atoms/ScrollingTitle.svelte
Normal file
41
src/components/atoms/ScrollingTitle.svelte
Normal file
@@ -0,0 +1,41 @@
|
||||
<script lang="ts">
|
||||
import { map } from '$utils/functions'
|
||||
|
||||
export let tag: string
|
||||
export let label: string = undefined
|
||||
export let parallax: number = undefined
|
||||
export let offset: number = 0
|
||||
|
||||
let scrollY: number
|
||||
let titleEl: HTMLElement
|
||||
|
||||
$: if (titleEl) {
|
||||
const start = titleEl.offsetTop + offset
|
||||
const end = titleEl.offsetTop + (titleEl.offsetHeight + offset) * 0.9
|
||||
parallax = map(scrollY, start, end, 0, 1, true)
|
||||
}
|
||||
|
||||
const classes = [
|
||||
'scrolling-title',
|
||||
'title-huge',
|
||||
$$props.class
|
||||
].join(' ').trim()
|
||||
</script>
|
||||
|
||||
<svelte:window bind:scrollY />
|
||||
|
||||
{#if tag === 'h1'}
|
||||
<h1 class={classes} aria-label={label}
|
||||
bind:this={titleEl}
|
||||
style="--parallax-x: {parallax};"
|
||||
>
|
||||
<slot />
|
||||
</h1>
|
||||
{:else if tag === 'p'}
|
||||
<p class={classes} aria-label={label}
|
||||
bind:this={titleEl}
|
||||
style="--parallax-x: {parallax};"
|
||||
>
|
||||
<slot />
|
||||
</p>
|
||||
{/if}
|
||||
@@ -3,8 +3,10 @@
|
||||
import { page } from '$app/stores'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
import SplitText from '$components/SplitText.svelte'
|
||||
import Button from '$components/atoms/Button.svelte'
|
||||
import IconEarth from '$components/atoms/IconEarth.svelte'
|
||||
import ScrollingTitle from '$components/atoms/ScrollingTitle.svelte'
|
||||
import BoxCTA from '$components/atoms/BoxCTA.svelte'
|
||||
import DiscoverText from '$components/atoms/DiscoverText.svelte'
|
||||
import PhotoCard from '$components/molecules/PhotoCard.svelte'
|
||||
@@ -17,8 +19,13 @@
|
||||
|
||||
const { settings, locations }: any = getContext('global')
|
||||
const { path } = $page
|
||||
|
||||
let scrollY: number, innerHeight: number
|
||||
let introTitleParallax = 0
|
||||
</script>
|
||||
|
||||
<svelte:window bind:scrollY bind:innerHeight />
|
||||
|
||||
<Metas
|
||||
title="Houses Of"
|
||||
description=""
|
||||
@@ -27,15 +34,19 @@
|
||||
|
||||
<main class="homepage">
|
||||
<section class="homepage__intro">
|
||||
<h1 style="display: none;">Houses Of The World</h1>
|
||||
<p class="homepage__title--houses title-huge">Houses</p>
|
||||
<p class="homepage__description text-medium">
|
||||
{settings.description}
|
||||
</p>
|
||||
<ScrollingTitle tag="h1" class="homepage__title--houses" label="Houses of the World" parallax={introTitleParallax} offsetTop={100}>
|
||||
<SplitText text="Houses" mode="chars" />
|
||||
</ScrollingTitle>
|
||||
|
||||
<Button text="Explore locations" url="{path}#locations">
|
||||
<IconEarth animate={true} />
|
||||
</Button>
|
||||
<div class="homepage__headline">
|
||||
<p class="text-medium">
|
||||
{settings.description}
|
||||
</p>
|
||||
|
||||
<Button text="Explore locations" url="{path}#locations">
|
||||
<IconEarth animate={true} />
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="homepage__photos">
|
||||
@@ -79,7 +90,10 @@
|
||||
|
||||
<section class="homepage__locations" id="locations">
|
||||
<InteractiveGlobe />
|
||||
<p class="homepage__title--world title-huge">World</p>
|
||||
|
||||
<ScrollingTitle tag="p" class="homepage__title--world" parallax={introTitleParallax} offset={-1 * innerHeight / 2}>
|
||||
<SplitText text="World" mode="chars" />
|
||||
</ScrollingTitle>
|
||||
|
||||
<Locations {locations} />
|
||||
</section>
|
||||
|
||||
5
src/style/atoms/_scrolling-title.scss
Normal file
5
src/style/atoms/_scrolling-title.scss
Normal file
@@ -0,0 +1,5 @@
|
||||
.scrolling-title {
|
||||
transform: translate3d(calc(-1px * var(--parallax-x) * 100), 0, 0);
|
||||
transition: transform 1.2s var(--ease-quart);
|
||||
will-change: transform;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
.homepage {
|
||||
// Site title
|
||||
&__title {
|
||||
// Houses
|
||||
&--houses {
|
||||
margin: -20px 0 0;
|
||||
color: $color-secondary;
|
||||
@@ -9,8 +10,15 @@
|
||||
|
||||
@include bp (sm) {
|
||||
margin-top: -100px;
|
||||
margin-left: calc(-1 * clamp(24px, 6vw, 64px));
|
||||
}
|
||||
|
||||
span {
|
||||
transition: none;
|
||||
letter-spacing: -0.06em;
|
||||
}
|
||||
}
|
||||
// World
|
||||
&--world {
|
||||
color: $color-primary-tertiary20;
|
||||
text-align: center;
|
||||
@@ -62,14 +70,22 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
// Text
|
||||
&__description {
|
||||
// Headline
|
||||
&__headline {
|
||||
max-width: 350px;
|
||||
margin: 100px auto 32px;
|
||||
margin: 100px auto 0;
|
||||
|
||||
@include bp (sm) {
|
||||
margin: 20px auto 32px;
|
||||
max-width: 524px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 24px;
|
||||
|
||||
@include bp (sm) {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
@import "atoms/discover";
|
||||
@import "atoms/box-cta";
|
||||
@import "atoms/site-title";
|
||||
@import "atoms/scrolling-title";
|
||||
@import "atoms/photo";
|
||||
|
||||
// Molecules
|
||||
|
||||
Reference in New Issue
Block a user