From f8b6b79ce1e0205e0d7ba077254451b6d8a61bb7 Mon Sep 17 00:00:00 2001 From: saiminh Date: Thu, 12 Oct 2023 23:45:07 +0200 Subject: [PATCH] first draft --- src/lib/components/ContactCanvas.svelte | 44 +- src/lib/components/Header.svelte | 13 + src/lib/components/HomeCanvas.svelte | 23 +- src/lib/components/MainNav.svelte | 24 +- src/lib/components/WorkCanvas.svelte | 6 +- src/lib/styles/global.scss | 33 +- src/lib/utils/createCanvasText.ts | 1 + src/routes/+layout.svelte | 1 - src/routes/+page.svelte | 132 ++-- src/routes/contact/+page.svelte | 77 +-- src/routes/service/+page.svelte | 49 +- src/routes/service/ServiceCanvas.svelte | 7 +- src/routes/success/+page.svelte | 120 +++- src/routes/work/+page.svelte | 218 +++++-- src/routes/work/[slug]/+page.server.ts | 10 +- src/routes/work/[slug]/+page.svelte | 509 +++++++++------- src/routes/work/[slug]/old+page.svelte | 279 +++++++++ src/routes/work/md/adidas.md | 9 +- src/routes/work/md/booking.md | 14 + src/routes/work/md/etosis.md | 26 + src/routes/work/md/formo.md | 21 +- src/routes/work/md/hatetracker.md | 21 + src/routes/work/md/jpl.md | 19 +- src/routes/work/md/letshost.md | 12 + src/routes/work/md/peak.md | 17 +- src/routes/work/md/uncommon.md | 20 +- src/routes/work/old+page.svelte | 71 +++ src/routes/work/old-work.scss | 113 ++++ src/routes/work/work.scss | 177 +++--- src/routes/work/workUtils.ts | 8 +- static/home/design-shapes.ai | 775 ++++++++++++------------ static/success/displacementMap.jpg | Bin 0 -> 42182 bytes static/success/envelope.png | Bin 0 -> 10709 bytes 33 files changed, 1913 insertions(+), 936 deletions(-) create mode 100644 src/routes/work/[slug]/old+page.svelte create mode 100644 src/routes/work/md/booking.md create mode 100644 src/routes/work/md/etosis.md create mode 100644 src/routes/work/md/hatetracker.md create mode 100644 src/routes/work/md/letshost.md create mode 100644 src/routes/work/old+page.svelte create mode 100644 src/routes/work/old-work.scss create mode 100644 static/success/displacementMap.jpg create mode 100644 static/success/envelope.png diff --git a/src/lib/components/ContactCanvas.svelte b/src/lib/components/ContactCanvas.svelte index 3154622..053a06d 100644 --- a/src/lib/components/ContactCanvas.svelte +++ b/src/lib/components/ContactCanvas.svelte @@ -41,6 +41,8 @@ onMount(()=>{ backgroundAlpha: 0, view: canvas, }); + + PIXI.Filter.defaultResolution = 2; //for debugging but Typescript has an issue with this: (globalThis as any).__PIXI_APP__ = app; @@ -64,24 +66,26 @@ onMount(()=>{ bulgegroup.addChild(bulgebg); let center = [0.5, 0.5]; + let bulgefilter = new BulgePinchFilter(); bulgefilter.radius = is_landscape ? xFrac(0.5) : xFrac(0.55); bulgefilter.strength = 0.5; bulgefilter.center = is_landscape ? center : [0.5, 0]; - bulgefilter.resolution = 2; + // bulgefilter.resolution = 2; let twistfilter = new TwistFilter(); twistfilter.angle = 0; - twistfilter.radius = window.innerWidth/2; - twistfilter.offset = new PIXI.Point(window.innerWidth/2, window.innerHeight/2); - twistfilter.resolution = 2; + twistfilter.radius = is_landscape ? window.innerWidth/4 : window.innerWidth/2; + twistfilter.offset = new PIXI.Point(window.innerWidth/2, window.innerHeight/3); + // twistfilter.resolution = 2; + bulgegroup.filters = [bulgefilter, twistfilter]; gsap.to(twistfilter, { - angle: .75, + angle: -1.33, duration: 1, - ease: 'elastic.out', + ease: 'elastic.out(2, 0.4)', delay: 2, onComplete: () => { is_twisted = true; @@ -174,13 +178,15 @@ onMount(()=>{ const pointerXfrac = pointerX - 0.5; const pointerYfrac = pointerY - 0.5; - gsap.to(mouse, { - duration: 0.5, - ease: 'power3.out', - overwrite: true, - x: e.clientX, - y: e.clientY, - }) + if (is_twisted){ + gsap.to(mouse, { + duration: 0.5, + ease: 'power3.out', + overwrite: true, + x: e.clientX, + y: e.clientY, + }) + } gsap.to(tween, { duration: .5, @@ -189,7 +195,7 @@ onMount(()=>{ x: 0.5 + pointerXfrac/2, y: 0.5 + pointerYfrac/6, }) - }) + }, { passive: true }) } @@ -202,12 +208,16 @@ onMount(()=>{ elapsed += delta; if (!is_landscape) { // bulgefilter.center = [(tween.x + Math.sin(elapsed/200)/20 ),(tween.y + Math.cos(elapsed/200)/20 )]; - bulgefilter.center = [(0.5 + Math.sin(elapsed/200)/20 ),(0.4 + Math.cos(elapsed/200)/20 )]; - twistfilter.offset = new PIXI.Point( twistfilter.offset.x + Math.sin(elapsed/100) - Math.sin(elapsed/100) * 2, twistfilter.offset.y ); + let movingCenter = [(0.5 + Math.sin(elapsed/200)/20 ),(0.33 + Math.cos(elapsed/200)/20 )]; + bulgefilter.center = movingCenter; + twistfilter.offset = new PIXI.Point( + window.innerWidth * movingCenter[0] , + window.innerHeight * movingCenter[1] + ); // bulgefilter.center = [0.5, 0.25]; } else { bulgefilter.center = [tween.x, tween.y]; - twistfilter.offset = new PIXI.Point(mouse.x, mouse.y); + is_twisted ? twistfilter.offset = new PIXI.Point(mouse.x, window.innerHeight/3) : null; } updateImgs(); updateText(); diff --git a/src/lib/components/Header.svelte b/src/lib/components/Header.svelte index 5372392..f560154 100644 --- a/src/lib/components/Header.svelte +++ b/src/lib/components/Header.svelte @@ -11,6 +11,19 @@ \ No newline at end of file diff --git a/src/lib/components/WorkCanvas.svelte b/src/lib/components/WorkCanvas.svelte index 300cd33..f326648 100644 --- a/src/lib/components/WorkCanvas.svelte +++ b/src/lib/components/WorkCanvas.svelte @@ -77,7 +77,9 @@ onMount( () => { bulgefilter.radius = is_landscape ? xFrac(0.5) : xFrac(0.6); bulgefilter.strength = is_landscape ? bulgeFactor : bulgeFactor * 1.25; bulgefilter.center = center; - bulgefilter.resolution = 2; + // bulgefilter.resolution = 2; + + PIXI.Filter.defaultResolution = 2; app.stage.filters = [bulgefilter]; @@ -208,7 +210,7 @@ onMount( () => { x: pointerX, y: pointerY, }) - }) + }, { passive: true }) } diff --git a/src/lib/styles/global.scss b/src/lib/styles/global.scss index 5d5715d..3a375c6 100644 --- a/src/lib/styles/global.scss +++ b/src/lib/styles/global.scss @@ -1,8 +1,9 @@ :root { --spacing-outer: 5vw; --spacing-nav: 5vw; - --color-bg: #2085e3; - --color-text: #ffe9e6; + // --color-bg: hsl(202, 58%, 39%); + --color-bg: hsl(0, 60%, 53%); + --color-text: #ffead9; --color-highlight: #1d0c12; // --color-bg: #000000; // --color-text: #FFFFFF; @@ -15,6 +16,7 @@ --spacing-nav: 2.5vw; } } + body { cursor: url('/cursor.svg'), auto; } @@ -52,13 +54,13 @@ h1, h2, h3, h4, h5 { letter-spacing: -0.025em; } h1 { - font-size: 3.5em; + font-size: 2.5em; } h2 { - font-size: 2em; + font-size: 1.5em; } h3 { - font-size: 1.5em; + font-size: 1.25em; } ul, ol { padding-left: 0; @@ -73,6 +75,12 @@ p, li { } a { color: inherit; + text-underline-offset: 0.25em; + text-decoration-thickness: 0.066em; + transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275); + &:hover { + text-underline-offset: 0.1em; + } } .cta { font-size: clamp(20px, 1.6vw, 1.6vw); @@ -95,8 +103,8 @@ a { transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275); &:hover { + color: var(--color-bg); @media screen and (min-width: 768px) { - // font-size: 1.05em; letter-spacing: 0.01em; } } @@ -116,6 +124,7 @@ a { transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275); } &:hover:before { + background-color: var(--color-text); width: calc(100% + 0.25em); height: calc(100% + 10px); left: -0.125em; @@ -125,10 +134,17 @@ a { &.button--primary { color: var(--color-text); + &:hover { + color: var(--color-highlight); + } &:before { background-color: var(--color-highlight); border: 2px solid var(--color-highlight); } + &:hover:before { + background-color: var(--color-text); + border: 2px solid var(--color-text); + } } &.button--xl { font-size: clamp(24px, 3.2vw, 3.2vw); @@ -164,4 +180,9 @@ a { position: absolute; top: 0; width: 100%; +} +.hide-on-mobile { + @media screen and (orientation: portrait) and (max-width: 767px) { + display: none; + } } \ No newline at end of file diff --git a/src/lib/utils/createCanvasText.ts b/src/lib/utils/createCanvasText.ts index f1e1251..81494e2 100644 --- a/src/lib/utils/createCanvasText.ts +++ b/src/lib/utils/createCanvasText.ts @@ -14,6 +14,7 @@ export default function createCanvasText( element: HTMLElement, stage: PIXI.Con const elemAlignment = elemStyles.getPropertyValue('text-align') || 'left'; const elemPosition = elem.getBoundingClientRect(); const elemTextTransform = elemStyles.getPropertyValue('text-transform') || 'none'; + if (elemTextTransform === 'uppercase') { elem.textContent = elem.textContent?.toUpperCase() as string; } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 5b27d80..8df4937 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -2,7 +2,6 @@ import '$lib/styles/global.scss'; import Header from '$lib/components/Header.svelte'; import Loader from '$lib/components/Loader.svelte'; - import { fade } from 'svelte/transition'; import { navigating } from '$app/stores'; export let data; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 10530b7..37290d2 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -4,6 +4,8 @@ import { onMount } from 'svelte'; import { gsap } from 'gsap'; import ScrollTrigger from 'gsap/dist/ScrollTrigger'; + import ScrollToPlugin from 'gsap/dist/ScrollToPlugin'; + import { goto } from '$app/navigation'; import SplitText from 'gsap/dist/SplitText'; import HomeIlluDev from '$lib/components/HomeIlluDev.svelte'; import HomeIlluShapes from '$lib/components/HomeIlluShapes.svelte'; @@ -16,7 +18,7 @@ mounted = true; - gsap.registerPlugin( ScrollTrigger, SplitText ); + gsap.registerPlugin( ScrollTrigger, ScrollToPlugin, SplitText ); const sections = document.querySelectorAll('section'); @@ -50,8 +52,8 @@ gsap.to(split.words, { duration: 1, yPercent: 0, opacity: 1, stagger: 0.05, ease: 'power4.out', scrollTrigger: { trigger: split.words, start: 'top 90%', end: 'bottom 70%', scrub: false } }) - if (section.querySelector('.toCanvas')) { - let splitp = new SplitText(section.querySelectorAll('.toCanvas'), { type: 'lines', linesClass: 'lineChildren' }); + if (section.querySelector('p')) { + let splitp = new SplitText(section.querySelectorAll('p'), { type: 'lines', linesClass: 'lineChildren' }); gsap.set(splitp.lines, { transformOrigin: '0% 100%' }); gsap.set(splitp.lines, { yPercent: 100, opacity: 0 }); gsap.to(splitp.lines, { duration: 1, yPercent: 0, opacity: 1, stagger: 0.05, ease: 'power4.out', @@ -61,9 +63,27 @@ } }) - canvasElems = Array.from(document.querySelectorAll('.lineChildren, .wordChildren')); + canvasElems = Array.from(document.querySelectorAll('.canvasized .lineChildren, .canvasized .wordChildren')); imgElems = Array.from(document.querySelectorAll('img')); + sections.forEach(section => { + //create a click eventlistener, that will scroll to the next section + section.addEventListener('click', (e) => { + e.preventDefault(); + //if the cursor is over a link, don't scroll and open the link's href location + let target = e.target as HTMLElement; + if (target?.closest('a')) { + goto(target.closest('a')?.getAttribute('href') || ''); + return; + } + + let nextSection = section.nextElementSibling as HTMLElement; + if (nextSection) { + gsap.to(window, { duration: 1, scrollTo: nextSection, ease: 'power4.inOut' }) + } + }) + }) + return () => { gsap.killTweensOf(canvasElems); ScrollTrigger.getAll().forEach( instance => instance.kill() ); @@ -75,18 +95,21 @@ {/if}
-
-

Hallo! I'm Simon. I forge websites that stand out with exemplary beauty.

+
+

I create digital experiences that stand out from the rest.

-
-
+
+

My name is Simon, I help my clients reach their audiences using my skills:

+
+
+

Creative Development

-

I fashion exquisitly tailored web experiences for discerning enterprises and their audiences.

+

I create exquisitly tailored web experiences for discerning enterprises and their audiences.

@@ -94,15 +117,16 @@

Visual Design

-

I'm also a seasoned designer, sculpting communication that's wickedly nice, full of jaw-dropping surprises, and utterly delightful.

+

I'm a seasoned designer, with a long list of succesfull projects and happy clients.

-
-

I work as a free agent. Both companies and noble causes can enlist my services for a reasonable wage.

-
- Enlist my services +
+

I work as a free agent. You can hire me for your noble enterprise.

+
@@ -125,7 +149,7 @@ section { scroll-snap-align: start; box-sizing: border-box; - padding: var(--spacing-outer); + padding: 0 var(--spacing-outer); min-height: 100svh; display: flex; flex-direction: column; @@ -152,13 +176,24 @@ padding: var(--spacing-outer) calc(var(--spacing-outer) * 2); } } - .intro-image { + .introduction { + h2 { + font-size: 1.53em; + letter-spacing: -0.033em; + margin-bottom: 0; + line-height: .9; + } + } + .dev-image { position:relative; left: 0; text-align: center; display: block; - margin: 0 0 -.5em 0; z-index: -2; + margin: -2em 0 -.5em 0; + @media screen and (min-width: 768px) { + margin: -1.5em 0 -.5em 0; + } } .design { overflow: hidden; @@ -170,29 +205,28 @@ margin: 0 auto; text-align: center; display: block; - margin-bottom: -1em; + margin: 0 auto; z-index: -2; - + @media screen and (min-width: 768px) { - width: 40%; + margin: 0 auto .5em auto; + width: 45%; } } - .more { + .hireme { @media screen and (min-width: 768px) { max-width: 95vw; } } - .more h2 { - margin-top: -2em; - margin-bottom: 1em; + .hireme h2 { + font-size: 1.53em; @media screen and (min-width: 768px) { margin-bottom: 0.5em; margin-top: 0; } } h1, h2 { - line-height: 1.1; - visibility: hidden; + line-height: .9; margin: 0; -webkit-touch-callout: none; /* Safari */ -webkit-user-select: none; /* Chrome */ @@ -206,33 +240,30 @@ } } h1 { - line-height: .9; - font-size: 13.25vw; + line-height: .85; + font-size: 14.75vw; + letter-spacing: -0.05em; margin-top: -.5em; - letter-spacing: -0.02em; - opacity: 0; + color: var(--color-highlight); @media screen and (min-width: 768px) { - font-size: 9vw; + font-size: 11vw; + } + + & > em { + color: var(--color-text); } } - h2 { - font-size: 1.5em; - letter-spacing: -0.033em; - margin-bottom: 0; - line-height: .9; - } - .toCanvas { + .canvasized h1, .canvasized h2 { + opacity: 0; visibility: hidden; + } + p { font-size: .66em; - margin: 1.25em 0 0.25em 0; - -webkit-touch-callout: none; /* Safari */ - -webkit-user-select: none; /* Chrome */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* Internet Explorer/Edge */ - user-select: none; + margin: 0 0 0.25em 0; @media screen and (min-width: 768px) { - font-size: 0.5em; + margin: 1em 0 0.25em 0; + font-size: 0.66em; } } a { @@ -243,14 +274,13 @@ user-select: none; } .cta { - margin-top: 0em; + margin-top: -.5em; padding-top: 0em; - text-align: center; @media screen and (min-width: 768px) { // background-color: var(--color-bg); // border-top: 1px solid var(--color-text); padding-top: 1em; - margin-top: 2em; + margin-top: 0em; } } \ No newline at end of file diff --git a/src/routes/contact/+page.svelte b/src/routes/contact/+page.svelte index 0e0d2a1..ad2e5ac 100644 --- a/src/routes/contact/+page.svelte +++ b/src/routes/contact/+page.svelte @@ -9,25 +9,25 @@ let contactFormVisible = false; let contactFormClickHandler = (e: Event) => { if (contactFormVisible) { - gsap.to('.wordChildren', { opacity: 1, yPercent: 0, duration: 1, ease: 'power4.inOut' }) - gsap.to('.alternatives > *', { opacity: 1, scale: 1, duration: .5, stagger: 0.1, ease: 'power4.inOut' }) + gsap.to('.wordChildren', { autoAlpha: 1, yPercent: 0, duration: 1, ease: 'power4.inOut' }) + gsap.to('.alternatives > *', { autoAlpha: 1, scale: 1, duration: .5, stagger: 0.1, ease: 'power4.inOut' }) gsap.fromTo('.formwrapper', - { opacity: 1, yPercent: 0 }, - { opacity: 0, yPercent: 50, duration: .6, ease: 'power4.inOut', onComplete: ()=>{ + { autoAlpha: 1, yPercent: 0 }, + { autoAlpha: 0, yPercent: 50, duration: .6, ease: 'power4.inOut', onComplete: () => { gsap.set('.formwrapper', { zIndex: -1 }) } } ) } else { - gsap.to('.wordChildren', { opacity: 1, yPercent: -200, duration: 1, ease: 'power4.inOut' }) - gsap.to('.alternatives > *', { opacity: 0, scale: 0.5, duration: .5, stagger: 0.1, ease: 'power4.inOut' }) + gsap.to('.wordChildren', { autoAlpha: 1, yPercent: -100, duration: 1, ease: 'power4.inOut' }) + gsap.to('.alternatives > *', { autoAlpha: 0, scale: 0.5, duration: .5, stagger: 0.1, ease: 'power4.inOut' }) gsap.set('.formwrapper', { zIndex: 2 }) gsap.fromTo('.formwrapper', - { opacity: 1, yPercent: 100 }, - { opacity: 1, yPercent: 0, duration: 1, ease: 'power4.inOut' } + { autoAlpha: 1, yPercent: 100 }, + { autoAlpha: 1, yPercent: 0, duration: 1, ease: 'power4.inOut' } ) gsap.fromTo('.formwrapper label > *', - { opacity: 0, yPercent: 100 }, - { opacity: 1, yPercent: 0, duration: .5, stagger: 0.0125, ease: 'power4.out', delay: .25} + { autoAlpha: 0, yPercent: 100 }, + { autoAlpha: 1, yPercent: 0, duration: .5, stagger: 0.0125, ease: 'power4.out', delay: .25} ) } contactFormVisible = !contactFormVisible; @@ -58,30 +58,29 @@ const introInElem = document.querySelector('.pagewrapper') as HTMLElement; gsap.fromTo(introInElem.querySelectorAll('.wordChildren'), { - opacity: 0, yPercent: -100 + autoAlpha: 0, yPercent: -100 }, { - opacity: 1, yPercent: 0, duration: 1.5, stagger: 0.025, ease: 'power4.inOut', + autoAlpha: 1, yPercent: 0, duration: 1.5, stagger: 0.025, ease: 'power4.inOut', }) gsap.fromTo(introInElem?.querySelectorAll('.alternatives p, .alternatives .button'), { - opacity: 0, yPercent: 100 + autoAlpha: 0, yPercent: 100 }, { - opacity: 1, yPercent: 0, duration: 1, stagger: 0.025, ease: 'power4.inOut', + autoAlpha: 1, yPercent: 0, duration: 1, stagger: 0.025, ease: 'power4.inOut', }) return () => { gsap.killTweensOf('.toCanvas, .wordChildren'); } }) -
-

Life is weird. Let's be weird together.

+

Let's be strange,
not strangers.

Choose your flavour of contact:

@@ -103,7 +102,7 @@