it's blue now
|
|
@ -26,5 +26,9 @@ module.exports = {
|
||||||
parser: '@typescript-eslint/parser'
|
parser: '@typescript-eslint/parser'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
rules: {
|
||||||
|
"no-await-in-loop": "error",
|
||||||
|
"no-promise-executor-return": "error",
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
132
src/lib/components/Faq.svelte
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import gsap from "gsap";
|
||||||
|
export let summary: string;
|
||||||
|
let details: HTMLElement;
|
||||||
|
let contentHeight: number;
|
||||||
|
let summaryHeight: number;
|
||||||
|
|
||||||
|
onMount( () => {
|
||||||
|
contentHeight = (details?.querySelector('.faq-content') as HTMLElement).offsetHeight;
|
||||||
|
summaryHeight = (details?.querySelector('summary') as HTMLElement).offsetHeight;
|
||||||
|
details.style.setProperty('--height', `${summaryHeight}px`);
|
||||||
|
details.style.height = `var(--height)`;
|
||||||
|
|
||||||
|
|
||||||
|
function resizeHandler() {
|
||||||
|
contentHeight = (details?.querySelector('.faq-content') as HTMLElement).offsetHeight;
|
||||||
|
summaryHeight = (details?.querySelector('summary') as HTMLElement).offsetHeight;
|
||||||
|
if ( details?.hasAttribute('open') ) {
|
||||||
|
details.style.setProperty('--height', `${contentHeight + summaryHeight}px`);
|
||||||
|
details.style.height = `var(--height)`;
|
||||||
|
} else {
|
||||||
|
details.style.setProperty('--height', `${summaryHeight}px`);
|
||||||
|
details.style.height = `var(--height)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', resizeHandler );
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', resizeHandler );
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function summaryClickHandler(e: Event){
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if ( details.hasAttribute('open') ) {
|
||||||
|
gsap.to( details, {
|
||||||
|
'--height': summaryHeight, duration: .4, ease: 'power4.out', overwrite: true,
|
||||||
|
onComplete: () => {
|
||||||
|
details.toggleAttribute('open')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
details.toggleAttribute('open');
|
||||||
|
contentHeight = (details?.querySelector('.faq-content') as HTMLElement).offsetHeight;
|
||||||
|
let fullHeight = contentHeight + summaryHeight;
|
||||||
|
gsap.to( details, {
|
||||||
|
'--height': fullHeight, duration: .5, ease: 'back.out(1)', overwrite: true
|
||||||
|
})
|
||||||
|
gsap.fromTo( details.querySelector('.faq-content'), {
|
||||||
|
opacity: 0, x: -60
|
||||||
|
}, {
|
||||||
|
opacity: 1, x: 0, duration: .5, ease: 'power3.out', overwrite: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<details bind:this={details}>
|
||||||
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
|
<summary on:click={summaryClickHandler} on:keyup={summaryClickHandler}>{summary}</summary>
|
||||||
|
<div class="faq-content">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
details {
|
||||||
|
--height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
transition: margin-bottom .3s ease-out;
|
||||||
|
}
|
||||||
|
details[open] {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
summary {
|
||||||
|
display: block;
|
||||||
|
cursor: url('/pointer.svg'), auto;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-size: 1em;
|
||||||
|
padding: 0.5em 0 0.5em 1.5em;
|
||||||
|
|
||||||
|
&:before, &:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 1em;
|
||||||
|
width: 17px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: var(--color-text);
|
||||||
|
transform-origin: center;
|
||||||
|
transition: transform .2s ease-in-out;
|
||||||
|
}
|
||||||
|
&:before {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
details[open] summary {
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.faq-content {
|
||||||
|
border-left: 1px solid;
|
||||||
|
margin-left: 8px;
|
||||||
|
padding: 1em 0 0 calc(1.5em - 8px);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
font-size: 1em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
:global(.faq-content p, .faq-content li){
|
||||||
|
font-size: 1em!important;
|
||||||
|
}
|
||||||
|
:global(.faq-content li){
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
:global(.faq-content > :first-child){
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
:global(.faq-content > :last-child){
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -20,17 +20,6 @@
|
||||||
display: block;
|
display: block;
|
||||||
margin: var(--spacing-nav);
|
margin: var(--spacing-nav);
|
||||||
cursor: url('/pointer.svg'), auto;
|
cursor: url('/pointer.svg'), auto;
|
||||||
}
|
text-decoration: none;
|
||||||
.header-nav {
|
|
||||||
@media screen and (max-width: 767px) {
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
width: 100%;
|
|
||||||
height: calc(36px + 2 * var(--spacing-nav));
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 3;
|
|
||||||
// border-top: 1px solid var(--color-text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -16,16 +16,24 @@ export let imgsToCanvas: Array<HTMLElement> = [];
|
||||||
let app: PIXI.Application;
|
let app: PIXI.Application;
|
||||||
let canvas: HTMLCanvasElement;
|
let canvas: HTMLCanvasElement;
|
||||||
|
|
||||||
|
|
||||||
onMount(()=>{
|
onMount(()=>{
|
||||||
|
|
||||||
|
function xFrac(x: number){
|
||||||
|
return window.innerWidth * x;
|
||||||
|
}
|
||||||
|
function yFrac(y: number){
|
||||||
|
return window.innerHeight * y;
|
||||||
|
}
|
||||||
|
|
||||||
let is_fine = window.matchMedia('(pointer:fine)').matches
|
let is_fine = window.matchMedia('(pointer:fine)').matches
|
||||||
let is_coarse = window.matchMedia('(pointer:coarse)').matches
|
let is_coarse = window.matchMedia('(pointer:coarse)').matches
|
||||||
|
let is_landscape = window.matchMedia('(orientation:landscape)').matches
|
||||||
|
let is_portrait = window.matchMedia('(orientation:portrait)').matches
|
||||||
|
|
||||||
gsap.registerPlugin(PixiPlugin, ScrollTrigger, SplitText);
|
gsap.registerPlugin(PixiPlugin, ScrollTrigger, SplitText);
|
||||||
|
|
||||||
app = new PIXI.Application({
|
app = new PIXI.Application({
|
||||||
resizeTo: window,
|
resizeTo: document.querySelector('.canvasResizeToThis') as HTMLElement,
|
||||||
antialias: true,
|
antialias: true,
|
||||||
autoDensity: true,
|
autoDensity: true,
|
||||||
resolution: 2,
|
resolution: 2,
|
||||||
|
|
@ -34,69 +42,49 @@ onMount(()=>{
|
||||||
});
|
});
|
||||||
|
|
||||||
//for debugging but Typescript has an issue with this:
|
//for debugging but Typescript has an issue with this:
|
||||||
// globalThis.__PIXI_APP__ = app as any;
|
(globalThis as any).__PIXI_APP__ = app;
|
||||||
|
|
||||||
PixiPlugin.registerPIXI(PIXI);
|
PixiPlugin.registerPIXI(PIXI);
|
||||||
|
|
||||||
function xFrac(x: number){
|
|
||||||
return window.innerWidth * x;
|
|
||||||
}
|
|
||||||
function yFrac(y: number){
|
|
||||||
return window.innerHeight * y;
|
|
||||||
}
|
|
||||||
|
|
||||||
let group = new PIXI.Container();
|
let bulgegroup = new PIXI.Container();
|
||||||
group.pivot.set(window.innerWidth / 2, window.innerHeight / 2);
|
bulgegroup.pivot.set(xFrac(0.5), yFrac(0.5));
|
||||||
group.x = window.innerWidth / 2;
|
bulgegroup.x = xFrac(0.5);
|
||||||
group.y = window.innerHeight / 2;
|
bulgegroup.y = yFrac(0.5);
|
||||||
app.stage.addChild(group);
|
app.stage.addChild(bulgegroup);
|
||||||
|
|
||||||
let recty = new PIXI.Graphics();
|
let bulgebg = new PIXI.Graphics();
|
||||||
recty.beginFill('rgb(0, 0, 0)');
|
bulgebg.beginFill('rgb(0, 0, 0)');
|
||||||
recty.drawRect(0, 0, xFrac(1), yFrac(1));
|
bulgebg.drawRect(0, 0, xFrac(1.2), yFrac(1.2));
|
||||||
recty.endFill();
|
bulgebg.endFill();
|
||||||
recty.alpha = 0;
|
bulgebg.alpha = 0;
|
||||||
recty.pivot.set(xFrac(.5), yFrac(.5));
|
bulgebg.pivot.set(xFrac(.5), yFrac(.5));
|
||||||
recty.x = xFrac(0.5);
|
bulgebg.x = xFrac(0.5);
|
||||||
recty.y = yFrac(0.5);
|
bulgebg.y = yFrac(0.5);
|
||||||
group.addChild(recty);
|
bulgegroup.addChild(bulgebg);
|
||||||
|
|
||||||
let center = [0.5, 0.5];
|
let center = [0.5, 0.5];
|
||||||
let bulgefilter = new BulgePinchFilter();
|
let bulgefilter = new BulgePinchFilter();
|
||||||
bulgefilter.radius = xFrac(0.45);
|
bulgefilter.radius = xFrac(0.5);
|
||||||
bulgefilter.strength = 0;
|
bulgefilter.strength = is_fine ? 0.5 : 0.4;
|
||||||
bulgefilter.center = center;
|
bulgefilter.center = center;
|
||||||
bulgefilter.resolution = 2;
|
bulgefilter.resolution = 2;
|
||||||
app.stage.filters = [bulgefilter];
|
|
||||||
|
bulgegroup.filters = [bulgefilter];
|
||||||
|
|
||||||
|
let opening_animation_running = false;
|
||||||
|
|
||||||
gsap.to(bulgefilter, {
|
let introTl = gsap.timeline();
|
||||||
|
introTl.to(bulgefilter, {
|
||||||
|
strength: 0.75,
|
||||||
|
duration: .75,
|
||||||
|
ease: 'power4.out',
|
||||||
|
}, 1.5)
|
||||||
|
introTl.to(bulgefilter, {
|
||||||
strength: is_fine ? 0.5 : 0.4,
|
strength: is_fine ? 0.5 : 0.4,
|
||||||
duration: 1.5,
|
duration: 1.25,
|
||||||
delay: 1,
|
ease: 'elastic.out(1.5, .2)',
|
||||||
ease: 'elastic.out(1.75, 0.3)',
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener( is_fine ? 'mousedown' : 'touchstart', (e)=>{
|
|
||||||
let target = e.target as HTMLElement;
|
|
||||||
if (target.tagName === 'H1' || target.tagName === 'H2' || target.tagName === 'P'){
|
|
||||||
gsap.to(bulgefilter, {
|
|
||||||
strength: 0,
|
|
||||||
duration: 1,
|
|
||||||
ease: 'elastic.out',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
window.addEventListener( is_fine ? 'mouseup' : 'touchend', (e)=>{
|
|
||||||
let target = e.target as HTMLElement;
|
|
||||||
if (target.tagName === 'H1' || target.tagName === 'H2' || target.tagName === 'P'){
|
|
||||||
gsap.to(bulgefilter, {
|
|
||||||
strength: 0.5,
|
|
||||||
duration: 2,
|
|
||||||
ease: 'elastic.out',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/*----------------------------------
|
/*----------------------------------
|
||||||
* Convert text to canvas using
|
* Convert text to canvas using
|
||||||
* createCanvasText function
|
* createCanvasText function
|
||||||
|
|
@ -108,12 +96,11 @@ onMount(()=>{
|
||||||
await tick();
|
await tick();
|
||||||
textsToCanvas.forEach((element) => {
|
textsToCanvas.forEach((element) => {
|
||||||
elems.push(element);
|
elems.push(element);
|
||||||
let canvasText = createCanvasText(element, app.stage);
|
let canvasText = createCanvasText(element, bulgegroup);
|
||||||
canvasTexts.push(canvasText);
|
canvasTexts.push(canvasText);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------
|
/*----------------------------------
|
||||||
* Function to update text on canvas
|
* Function to update text on canvas
|
||||||
* runs in the Ticker
|
* runs in the Ticker
|
||||||
|
|
@ -121,8 +108,11 @@ onMount(()=>{
|
||||||
function updateText(){
|
function updateText(){
|
||||||
canvasTexts.forEach((text, index) => {
|
canvasTexts.forEach((text, index) => {
|
||||||
let headlinePosition = elems[index].getBoundingClientRect();
|
let headlinePosition = elems[index].getBoundingClientRect();
|
||||||
|
headlinePosition.x = headlinePosition.x + xFrac(0.1);
|
||||||
|
headlinePosition.y = headlinePosition.y + yFrac(0.1);
|
||||||
text.position.set(headlinePosition.x, headlinePosition.y);
|
text.position.set(headlinePosition.x, headlinePosition.y);
|
||||||
text.alpha = elems[index].style.opacity as unknown as number;
|
text.alpha = elems[index].style.opacity as unknown as number;
|
||||||
|
text.style.fill = window.getComputedStyle(elems[index]).color;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,8 +135,6 @@ onMount(()=>{
|
||||||
convertImgs();
|
convertImgs();
|
||||||
convertText();
|
convertText();
|
||||||
}, 100);
|
}, 100);
|
||||||
// convertImgs();
|
|
||||||
// convertText();
|
|
||||||
|
|
||||||
/*----------------------------------
|
/*----------------------------------
|
||||||
* Function to update text on canvas
|
* Function to update text on canvas
|
||||||
|
|
@ -155,6 +143,8 @@ onMount(()=>{
|
||||||
function updateImgs(){
|
function updateImgs(){
|
||||||
canvasImgs.forEach((image, index) => {
|
canvasImgs.forEach((image, index) => {
|
||||||
let imagePosition = imgElems[index].getBoundingClientRect();
|
let imagePosition = imgElems[index].getBoundingClientRect();
|
||||||
|
imagePosition.x = imagePosition.x + xFrac(0.1);
|
||||||
|
imagePosition.y = imagePosition.y + yFrac(0.1);
|
||||||
image.position.set(imagePosition.x, imagePosition.y);
|
image.position.set(imagePosition.x, imagePosition.y);
|
||||||
image.width = imagePosition.width;
|
image.width = imagePosition.width;
|
||||||
image.height = imagePosition.height;
|
image.height = imagePosition.height;
|
||||||
|
|
@ -164,26 +154,37 @@ onMount(()=>{
|
||||||
/*----------------------------------
|
/*----------------------------------
|
||||||
* Mousemove events
|
* Mousemove events
|
||||||
*----------------------------------*/
|
*----------------------------------*/
|
||||||
let tween = {
|
let tween = {
|
||||||
x: 0.5,
|
x: 0.5,
|
||||||
y: is_fine ? 0.5 : 250/window.innerHeight,
|
y: is_fine ? 0.5 : 250/window.innerHeight,
|
||||||
};
|
};
|
||||||
|
const mouse = {
|
||||||
|
x: xFrac(0.5),
|
||||||
|
y: yFrac(0.5),
|
||||||
|
}
|
||||||
|
|
||||||
if (is_fine) {
|
if (is_fine) {
|
||||||
window.addEventListener('mousemove', (e) => {
|
window.addEventListener('mousemove', (e) => {
|
||||||
|
if (opening_animation_running) return;
|
||||||
const pointerX = e.clientX / window.innerWidth;
|
const pointerX = e.clientX / window.innerWidth;
|
||||||
const pointerY = e.clientY / window.innerHeight;
|
const pointerY = e.clientY / window.innerHeight;
|
||||||
const pointerXfrac = pointerX - 0.5;
|
const pointerXfrac = pointerX - 0.5;
|
||||||
const pointerYfrac = pointerY - 0.5;
|
const pointerYfrac = pointerY - 0.5;
|
||||||
|
|
||||||
// center = [(0.5 + pointerXfrac/10),(0.5 + pointerYfrac/10)];
|
gsap.to(mouse, {
|
||||||
|
duration: 0.5,
|
||||||
|
ease: 'power3.out',
|
||||||
|
overwrite: true,
|
||||||
|
x: e.clientX,
|
||||||
|
y: e.clientY,
|
||||||
|
})
|
||||||
|
|
||||||
gsap.to(tween, {
|
gsap.to(tween, {
|
||||||
duration: .5,
|
duration: .5,
|
||||||
ease: 'power3.out',
|
ease: 'power3.out',
|
||||||
overwrite: true,
|
overwrite: true,
|
||||||
x: 0.5 + pointerXfrac/10,
|
x: 0.5 + pointerXfrac/2,
|
||||||
y: 0.5 + pointerYfrac/10,
|
y: 0.5 + pointerYfrac/2,
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
@ -197,7 +198,11 @@ onMount(()=>{
|
||||||
|
|
||||||
app.ticker.add((delta) => {
|
app.ticker.add((delta) => {
|
||||||
elapsed += delta;
|
elapsed += delta;
|
||||||
bulgefilter.center = [(tween.x + Math.sin(elapsed/200)/20 ),(tween.y + Math.cos(elapsed/200)/20 )];
|
if (is_coarse) {
|
||||||
|
bulgefilter.center = [(tween.x + Math.sin(elapsed/200)/20 ),(tween.y + Math.cos(elapsed/200)/20 )];
|
||||||
|
} else {
|
||||||
|
bulgefilter.center = [tween.x, tween.y];
|
||||||
|
}
|
||||||
updateImgs();
|
updateImgs();
|
||||||
updateText();
|
updateText();
|
||||||
})
|
})
|
||||||
|
|
@ -205,6 +210,11 @@ onMount(()=>{
|
||||||
window.addEventListener('resize', (e) => {
|
window.addEventListener('resize', (e) => {
|
||||||
tween.y = is_fine ? 0.5 : 250/window.innerHeight;
|
tween.y = is_fine ? 0.5 : 250/window.innerHeight;
|
||||||
})
|
})
|
||||||
|
return () => {
|
||||||
|
gsap.killTweensOf(imgElems);
|
||||||
|
gsap.killTweensOf(elems);
|
||||||
|
ScrollTrigger.getAll().forEach( instance => instance.kill() );
|
||||||
|
}
|
||||||
}) // <- end onMount
|
}) // <- end onMount
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
|
|
@ -220,8 +230,10 @@ onDestroy(() => {
|
||||||
<style>
|
<style>
|
||||||
canvas {
|
canvas {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: -10vh;
|
||||||
left: 0;
|
left: -10vw;
|
||||||
|
width: 120vw;
|
||||||
|
height: 120vh;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
254
src/lib/components/HomeIlluDev.svelte
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { gsap } from 'gsap';
|
||||||
|
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger';
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
|
||||||
|
gsap.registerPlugin(ScrollTrigger);
|
||||||
|
|
||||||
|
gsap.set('#fingers *', { transformOrigin: '100% 66%' });
|
||||||
|
|
||||||
|
let introIsPlaying = true;
|
||||||
|
|
||||||
|
const keyPress = (key: HTMLElement) => {
|
||||||
|
let tl = gsap.timeline({ delay: Math.random() * 3, repeat: 0, paused: true});
|
||||||
|
tl.to( key, { duration: .3, yPercent: 20, zIndex: -1, ease: 'power3.in'})
|
||||||
|
.to( key, { duration: .3, yPercent: 0, ease: 'power3.in', onComplete: () => {
|
||||||
|
keyPress(key);
|
||||||
|
tl.kill();
|
||||||
|
} })
|
||||||
|
tl.play();
|
||||||
|
}
|
||||||
|
const initKeys = () => {
|
||||||
|
document.querySelectorAll("#keys path").forEach( key => {
|
||||||
|
keyPress(key as HTMLElement);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const fingerMove = (finger: HTMLElement) => {
|
||||||
|
gsap.to( finger, { duration: .2, rotateZ: Math.random() * 10 + 5, ease: 'power3.in', delay: Math.random(), repeat: -1, yoyo: true })
|
||||||
|
}
|
||||||
|
const moveHandToRandom = () => {
|
||||||
|
if (introIsPlaying) {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
gsap.to( '#hand', {
|
||||||
|
duration: .6,
|
||||||
|
xPercent: Math.random() * -80,
|
||||||
|
yPercent: Math.random() * -20,
|
||||||
|
rotateZ: Math.random() * 20 - 10,
|
||||||
|
ease: 'power3.in',
|
||||||
|
onComplete: () => moveHandToRandom()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const initHand = () => {
|
||||||
|
document.querySelectorAll("#fingers *").forEach( finger => {
|
||||||
|
fingerMove(finger as HTMLElement);
|
||||||
|
})
|
||||||
|
moveHandToRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
let introTl = gsap.timeline( {
|
||||||
|
scrollTrigger: { trigger: '#hank', start: 'top 50%', end: 'top top' }
|
||||||
|
});
|
||||||
|
introTl.set('#hand', {
|
||||||
|
yPercent: -100,
|
||||||
|
rotateZ: 40,
|
||||||
|
autoAlpha: 0,
|
||||||
|
})
|
||||||
|
introTl.set('#keys path', {
|
||||||
|
y: 1000,
|
||||||
|
autoAlpha: 0,
|
||||||
|
})
|
||||||
|
introTl.to('#keys path', {
|
||||||
|
duration: .66,
|
||||||
|
y: 0,
|
||||||
|
autoAlpha: 1,
|
||||||
|
stagger: {
|
||||||
|
each: .0025,
|
||||||
|
from: 'random'
|
||||||
|
},
|
||||||
|
ease: 'power3.out',
|
||||||
|
onComplete: () => initKeys()
|
||||||
|
}, 0);
|
||||||
|
introTl.to('#hand', {
|
||||||
|
yPercent: 0,
|
||||||
|
rotateZ: 0,
|
||||||
|
autoAlpha: 1,
|
||||||
|
duration: 1,
|
||||||
|
ease: 'power4.inOut',
|
||||||
|
onComplete: () => {
|
||||||
|
introIsPlaying = false;
|
||||||
|
initHand();
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
gsap.killTweensOf("#hand, #keys path, #fingers *");
|
||||||
|
introTl.kill();
|
||||||
|
ScrollTrigger.getAll().forEach( instance => instance.kill() );
|
||||||
|
introIsPlaying = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg id="hank" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 2000 1000" width="2000" height="1000">
|
||||||
|
<g id="keyboard">
|
||||||
|
<polygon id="back" class="st0" points="1986.2,933.8 21.4,933.8 198,468.4 1768.8,468.4 "/>
|
||||||
|
<g id="keys">
|
||||||
|
<path class="st1" d="M278.5,534.6c-0.5,1.6-2.8,3-5.1,3h-50.2c-2.3,0-3.7-1.3-3.1-3l12.5-35.1c0.6-1.6,2.8-2.8,5.1-2.8h49.1 c2.2,0,3.6,1.3,3.1,2.8L278.5,534.6z"/>
|
||||||
|
<path class="st1" d="M257.4,599.7c-0.6,1.7-2.9,3.2-5.3,3.2h-51.9c-2.4,0-3.8-1.4-3.2-3.2l13.3-37.5c0.6-1.7,3-3,5.3-3h50.7 c2.3,0,3.7,1.4,3.2,3L257.4,599.7z"/>
|
||||||
|
<path class="st1" d="M327.8,599.7c-0.5,1.7-2.8,3.2-5.2,3.2h-51.9c-2.4,0-3.8-1.4-3.3-3.2l12-37.5c0.5-1.7,2.8-3,5.1-3h50.7 c2.3,0,3.8,1.4,3.3,3L327.8,599.7z"/>
|
||||||
|
<path class="st1" d="M398.2,599.7c-0.4,1.7-2.7,3.2-5.1,3.2h-51.9c-2.4,0-3.9-1.4-3.4-3.2l10.7-37.5c0.5-1.7,2.7-3,5-3h50.7 c2.3,0,3.8,1.4,3.4,3L398.2,599.7z"/>
|
||||||
|
<path class="st1" d="M468.7,599.7c-0.4,1.7-2.6,3.2-5,3.2h-51.9c-2.4,0-3.9-1.4-3.5-3.2l9.3-37.5c0.4-1.7,2.6-3,4.9-3h50.7 c2.3,0,3.9,1.4,3.5,3L468.7,599.7z"/>
|
||||||
|
<path class="st1" d="M539.1,599.7c-0.3,1.7-2.5,3.2-4.9,3.2h-51.9c-2.4,0-4-1.4-3.6-3.2l8-37.5c0.4-1.7,2.5-3,4.8-3h50.7 c2.3,0,3.9,1.4,3.6,3L539.1,599.7z"/>
|
||||||
|
<path class="st1" d="M609.5,599.7c-0.3,1.7-2.4,3.2-4.7,3.2h-51.9c-2.4,0-4-1.4-3.7-3.2l6.7-37.5c0.3-1.7,2.4-3,4.7-3h50.7 c2.3,0,4,1.4,3.7,3L609.5,599.7z"/>
|
||||||
|
<path class="st1" d="M680,599.7c-0.2,1.7-2.3,3.2-4.6,3.2h-51.9c-2.4,0-4.1-1.4-3.8-3.2l5.3-37.5c0.2-1.7,2.3-3,4.6-3h50.7 c2.3,0,4,1.4,3.8,3L680,599.7z"/>
|
||||||
|
<path class="st1" d="M750.4,599.7c-0.1,1.7-2.2,3.2-4.5,3.2H694c-2.4,0-4.1-1.4-3.9-3.2l4-37.5c0.2-1.7,2.2-3,4.5-3h50.7 c2.3,0,4.1,1.4,4,3L750.4,599.7z"/>
|
||||||
|
<path class="st1" d="M820.9,599.7c-0.1,1.7-2.1,3.2-4.4,3.2h-51.9c-2.4,0-4.2-1.4-4.1-3.2l2.7-37.5c0.1-1.7,2.1-3,4.4-3h50.7 c2.3,0,4.1,1.4,4.1,3L820.9,599.7z"/>
|
||||||
|
<path class="st1" d="M891.3,599.7c0,1.7-1.9,3.2-4.3,3.2h-51.9c-2.4,0-4.2-1.4-4.2-3.2l1.3-37.5c0.1-1.7,2-3,4.3-3h50.7 c2.3,0,4.2,1.4,4.2,3L891.3,599.7z"/>
|
||||||
|
<path class="st1" d="M961.7,599.7c0.1,1.7-1.8,3.2-4.2,3.2h-51.9c-2.4,0-4.3-1.4-4.3-3.2l0-37.5c0-1.7,1.9-3,4.2-3h50.7 c2.3,0,4.2,1.4,4.3,3L961.7,599.7z"/>
|
||||||
|
<path class="st1" d="M1032.2,599.7c0.1,1.7-1.7,3.2-4.1,3.2h-51.9c-2.4,0-4.3-1.4-4.4-3.2l-1.3-37.5c-0.1-1.7,1.8-3,4.1-3h50.7 c2.3,0,4.3,1.4,4.4,3L1032.2,599.7z"/>
|
||||||
|
<path class="st1" d="M1102.6,599.7c0.2,1.7-1.6,3.2-4,3.2h-51.9c-2.4,0-4.4-1.4-4.5-3.2l-2.7-37.5c-0.1-1.7,1.7-3,4-3h50.7 c2.3,0,4.3,1.4,4.5,3L1102.6,599.7z"/>
|
||||||
|
<path class="st1" d="M1234.8,599.7c0.3,1.7-1.4,3.2-3.7,3.2h-113.7c-2.4,0-4.4-1.4-4.6-3.2l-4-37.5c-0.2-1.7,1.6-3,3.9-3h111.2 c2.3,0,4.4,1.4,4.7,3L1234.8,599.7z"/>
|
||||||
|
<path class="st1" d="M268.3,655.1c-0.6,1.8-3,3.3-5.4,3.3h-82.3c-2.4,0-3.9-1.5-3.2-3.3l14.1-39.6c0.6-1.8,3.1-3.2,5.4-3.2h80.4 c2.4,0,3.8,1.4,3.3,3.2L268.3,655.1z"/>
|
||||||
|
<path class="st1" d="M269.4,713.4c-0.6,1.9-3.1,3.5-5.6,3.5H160c-2.5,0-4-1.6-3.3-3.5l14.9-41.9c0.7-1.9,3.2-3.4,5.6-3.4h101.4 c2.4,0,4,1.5,3.4,3.4L269.4,713.4z"/>
|
||||||
|
<path class="st1" d="M289.9,775.1c-0.6,2.1-3.2,3.7-5.7,3.7H138.1c-2.6,0-4.1-1.7-3.3-3.7l15.8-44.4c0.7-2,3.3-3.6,5.8-3.6H299 c2.5,0,4.1,1.6,3.5,3.6L289.9,775.1z"/>
|
||||||
|
<path class="st1" d="M214,839.5c-0.7,2.2-3.4,4-6,4h-92.7c-2.6,0-4.2-1.8-3.4-4l16.7-47c0.7-2.1,3.4-3.8,6-3.8h90.4 c2.6,0,4.1,1.7,3.5,3.8L214,839.5z"/>
|
||||||
|
<path class="st1" d="M342.8,655.1c-0.5,1.8-2.9,3.3-5.3,3.3h-53.3c-2.4,0-3.9-1.5-3.4-3.3l12.1-39.6c0.5-1.8,2.9-3.2,5.3-3.2h52.1 c2.4,0,3.9,1.4,3.4,3.2L342.8,655.1z"/>
|
||||||
|
<path class="st1" d="M345.2,713.4c-0.5,1.9-3,3.5-5.5,3.5h-54.8c-2.5,0-4.1-1.6-3.5-3.5l12.4-41.9c0.5-1.9,3-3.4,5.4-3.4h53.6 c2.4,0,4,1.5,3.5,3.4L345.2,713.4z"/>
|
||||||
|
<path class="st1" d="M422.1,713.4c-0.4,1.9-2.8,3.5-5.3,3.5H362c-2.5,0-4.1-1.6-3.6-3.5l10.8-41.9c0.5-1.9,2.9-3.4,5.3-3.4h53.6 c2.4,0,4.1,1.5,3.6,3.4L422.1,713.4z"/>
|
||||||
|
<path class="st1" d="M369.3,775.1c-0.5,2.1-3,3.7-5.6,3.7h-56.4c-2.6,0-4.2-1.7-3.6-3.7l12.3-44.4c0.5-2,3-3.6,5.5-3.6h55.1 c2.5,0,4.1,1.6,3.7,3.6L369.3,775.1z"/>
|
||||||
|
<path class="st1" d="M294.5,839.5c-0.6,2.2-3.2,4-5.9,4h-58.1c-2.6,0-4.3-1.8-3.6-4l14.3-47c0.6-2.1,3.3-3.8,5.8-3.8h56.7 c2.6,0,4.2,1.7,3.6,3.8L294.5,839.5z"/>
|
||||||
|
<path class="st1" d="M376.1,839.5c-0.5,2.2-3.1,4-5.7,4h-58.1c-2.6,0-4.3-1.8-3.7-4l12.5-47c0.6-2.1,3.1-3.8,5.7-3.8h56.7 c2.6,0,4.3,1.7,3.8,3.8L376.1,839.5z"/>
|
||||||
|
<path class="st1" d="M456.9,839.5c-0.4,2.2-3,4-5.6,4h-58.1c-2.6,0-4.4-1.8-3.9-4l10.8-47c0.5-2.1,3-3.8,5.5-3.8h56.7 c2.6,0,4.3,1.7,3.9,3.8L456.9,839.5z"/>
|
||||||
|
<path class="st1" d="M942.9,839.5c0,2.2-2.1,4-4.7,4H473.5c-2.6,0-4.4-1.8-4-4l9.1-47c0.4-2.1,2.8-3.8,5.4-3.8h453.2 c2.6,0,4.7,1.7,4.7,3.8L942.9,839.5z"/>
|
||||||
|
<path class="st1" d="M449.1,775.1c-0.4,2.1-2.9,3.7-5.4,3.7h-56.4c-2.6,0-4.2-1.7-3.8-3.7l10.6-44.4c0.5-2,2.9-3.6,5.4-3.6h55.1 c2.5,0,4.2,1.6,3.8,3.6L449.1,775.1z"/>
|
||||||
|
<path class="st1" d="M528.8,775.1c-0.4,2.1-2.7,3.7-5.3,3.7h-56.4c-2.6,0-4.3-1.7-3.9-3.7l9-44.4c0.4-2,2.8-3.6,5.3-3.6h55.1 c2.5,0,4.3,1.6,3.9,3.6L528.8,775.1z"/>
|
||||||
|
<path class="st1" d="M608.6,775.1c-0.3,2.1-2.6,3.7-5.2,3.7H547c-2.6,0-4.4-1.7-4-3.7l7.4-44.4c0.3-2,2.6-3.6,5.1-3.6h55.1 c2.5,0,4.3,1.6,4.1,3.6L608.6,775.1z"/>
|
||||||
|
<path class="st1" d="M688.3,775.1c-0.2,2.1-2.5,3.7-5,3.7h-56.4c-2.6,0-4.4-1.7-4.2-3.7l5.7-44.4c0.3-2,2.5-3.6,5-3.6h55.1 c2.5,0,4.4,1.6,4.2,3.6L688.3,775.1z"/>
|
||||||
|
<path class="st1" d="M768.1,775.1c-0.1,2.1-2.3,3.7-4.9,3.7h-56.4c-2.6,0-4.5-1.7-4.3-3.7l4.1-44.4c0.2-2,2.4-3.6,4.9-3.6h55.1 c2.5,0,4.4,1.6,4.3,3.6L768.1,775.1z"/>
|
||||||
|
<path class="st1" d="M847.8,775.1c-0.1,2.1-2.2,3.7-4.7,3.7h-56.4c-2.6,0-4.6-1.7-4.4-3.7l2.5-44.4c0.1-2,2.2-3.6,4.7-3.6h55.1 c2.5,0,4.5,1.6,4.5,3.6L847.8,775.1z"/>
|
||||||
|
<path class="st1" d="M927.6,775.1c0,2.1-2,3.7-4.6,3.7h-56.4c-2.6,0-4.6-1.7-4.6-3.7l0.8-44.4c0-2,2.1-3.6,4.6-3.6h55.1 c2.5,0,4.6,1.6,4.6,3.6L927.6,775.1z"/>
|
||||||
|
<path class="st1" d="M1007.3,775.1c0.1,2.1-1.9,3.7-4.5,3.7h-56.4c-2.6,0-4.7-1.7-4.7-3.7l-0.8-44.4c0-2,2-3.6,4.5-3.6h55.1 c2.5,0,4.6,1.6,4.7,3.6L1007.3,775.1z"/>
|
||||||
|
<path class="st1" d="M1028.2,839.5c0.1,2.2-1.9,4-4.6,4h-58.1c-2.6,0-4.8-1.8-4.9-4l-1.2-47c-0.1-2.1,2-3.8,4.6-3.8h56.7 c2.6,0,4.8,1.7,4.9,3.8L1028.2,839.5z"/>
|
||||||
|
<path class="st1" d="M1110.5,839.5c0.2,2.2-1.8,4-4.4,4h-58.1c-2.6,0-4.9-1.8-5-4l-3-47c-0.1-2.1,1.9-3.8,4.4-3.8h56.7 c2.6,0,4.8,1.7,5,3.8L1110.5,839.5z"/>
|
||||||
|
<path class="st1" d="M1192.7,839.5c0.3,2.2-1.6,4-4.3,4h-58.1c-2.6,0-5-1.8-5.2-4l-4.7-47c-0.2-2.1,1.7-3.8,4.3-3.8h56.7 c2.6,0,4.9,1.7,5.2,3.8L1192.7,839.5z"/>
|
||||||
|
<path class="st1" d="M1275,839.5c0.4,2.2-1.5,4-4.1,4h-58.1c-2.6,0-5-1.8-5.3-4l-6.5-47c-0.3-2.1,1.6-3.8,4.2-3.8h56.7 c2.6,0,5,1.7,5.3,3.8L1275,839.5z"/>
|
||||||
|
<path class="st1" d="M1087.1,775.1c0.2,2.1-1.8,3.7-4.3,3.7h-56.4c-2.6,0-4.7-1.7-4.9-3.7l-2.5-44.4c-0.1-2,1.8-3.6,4.3-3.6h55.1 c2.5,0,4.7,1.6,4.8,3.6L1087.1,775.1z"/>
|
||||||
|
<path class="st1" d="M1264.2,775.1c0.3,2.1-1.5,3.7-4,3.7h-154c-2.6,0-4.8-1.7-5-3.7l-4.1-44.4c-0.2-2,1.7-3.6,4.2-3.6h150.3 c2.5,0,4.8,1.6,5.1,3.6L1264.2,775.1z"/>
|
||||||
|
<path class="st1" d="M499.1,713.4c-0.4,1.9-2.7,3.5-5.2,3.5h-54.8c-2.5,0-4.2-1.6-3.7-3.5l9.3-41.9c0.4-1.9,2.7-3.4,5.2-3.4h53.6 c2.4,0,4.1,1.5,3.8,3.4L499.1,713.4z"/>
|
||||||
|
<path class="st1" d="M576.1,713.4c-0.3,1.9-2.6,3.5-5.1,3.5h-54.8c-2.5,0-4.2-1.6-3.9-3.5l7.8-41.9c0.3-1.9,2.6-3.4,5-3.4h53.6 c2.4,0,4.2,1.5,3.9,3.4L576.1,713.4z"/>
|
||||||
|
<path class="st1" d="M653,713.4c-0.2,1.9-2.5,3.5-4.9,3.5h-54.8c-2.5,0-4.3-1.6-4-3.5l6.2-41.9c0.3-1.9,2.5-3.4,4.9-3.4H654 c2.4,0,4.2,1.5,4,3.4L653,713.4z"/>
|
||||||
|
<path class="st1" d="M730,713.4c-0.2,1.9-2.3,3.5-4.8,3.5h-54.8c-2.5,0-4.3-1.6-4.1-3.5l4.7-41.9c0.2-1.9,2.4-3.4,4.8-3.4h53.6 c2.4,0,4.3,1.5,4.1,3.4L730,713.4z"/>
|
||||||
|
<path class="st1" d="M807,713.4c-0.1,1.9-2.2,3.5-4.7,3.5h-54.8c-2.5,0-4.4-1.6-4.3-3.5l3.2-41.9c0.1-1.9,2.2-3.4,4.7-3.4h53.6 c2.4,0,4.3,1.5,4.3,3.4L807,713.4z"/>
|
||||||
|
<path class="st1" d="M883.9,713.4c0,1.9-2.1,3.5-4.6,3.5h-54.8c-2.5,0-4.5-1.6-4.4-3.5l1.6-41.9c0.1-1.9,2.1-3.4,4.5-3.4h53.6 c2.4,0,4.4,1.5,4.4,3.4L883.9,713.4z"/>
|
||||||
|
<path class="st1" d="M960.9,713.4c0.1,1.9-1.9,3.5-4.4,3.5h-54.8c-2.5,0-4.5-1.6-4.5-3.5l0.1-41.9c0-1.9,2-3.4,4.4-3.4h53.6 c2.4,0,4.5,1.5,4.5,3.4L960.9,713.4z"/>
|
||||||
|
<path class="st1" d="M1037.8,713.4c0.1,1.9-1.8,3.5-4.3,3.5h-54.8c-2.5,0-4.6-1.6-4.6-3.5l-1.4-41.9c-0.1-1.9,1.9-3.4,4.3-3.4 h53.6c2.4,0,4.5,1.5,4.6,3.4L1037.8,713.4z"/>
|
||||||
|
<path class="st1" d="M1114.8,713.4c0.2,1.9-1.7,3.5-4.2,3.5h-54.8c-2.5,0-4.6-1.6-4.8-3.5l-3-41.9c-0.1-1.9,1.7-3.4,4.2-3.4h53.6 c2.4,0,4.6,1.5,4.8,3.4L1114.8,713.4z"/>
|
||||||
|
<path class="st1" d="M416.9,655.1c-0.4,1.8-2.8,3.3-5.2,3.3h-53.3c-2.4,0-4-1.5-3.5-3.3l10.6-39.6c0.5-1.8,2.8-3.2,5.2-3.2h52.1 c2.4,0,4,1.4,3.5,3.2L416.9,655.1z"/>
|
||||||
|
<path class="st1" d="M491,655.1c-0.4,1.8-2.7,3.3-5.1,3.3h-53.3c-2.4,0-4-1.5-3.6-3.3l9.2-39.6c0.4-1.8,2.7-3.2,5-3.2h52.1 c2.4,0,4,1.4,3.7,3.2L491,655.1z"/>
|
||||||
|
<path class="st1" d="M565.1,655.1c-0.3,1.8-2.5,3.3-4.9,3.3h-53.3c-2.4,0-4.1-1.5-3.7-3.3l7.7-39.6c0.3-1.8,2.6-3.2,4.9-3.2h52.1 c2.4,0,4.1,1.4,3.8,3.2L565.1,655.1z"/>
|
||||||
|
<path class="st1" d="M639.3,655.1c-0.2,1.8-2.4,3.3-4.8,3.3h-53.3c-2.4,0-4.2-1.5-3.9-3.3l6.3-39.6c0.3-1.8,2.4-3.2,4.8-3.2h52.1 c2.4,0,4.1,1.4,3.9,3.2L639.3,655.1z"/>
|
||||||
|
<path class="st1" d="M713.4,655.1c-0.2,1.8-2.3,3.3-4.7,3.3h-53.3c-2.4,0-4.2-1.5-4-3.3l4.9-39.6c0.2-1.8,2.3-3.2,4.7-3.2H713 c2.4,0,4.2,1.4,4,3.2L713.4,655.1z"/>
|
||||||
|
<path class="st1" d="M787.5,655.1c-0.1,1.8-2.2,3.3-4.6,3.3h-53.3c-2.4,0-4.3-1.5-4.1-3.3l3.4-39.6c0.2-1.8,2.2-3.2,4.6-3.2h52.1 c2.4,0,4.2,1.4,4.1,3.2L787.5,655.1z"/>
|
||||||
|
<path class="st1" d="M861.6,655.1c0,1.8-2,3.3-4.5,3.3h-53.3c-2.4,0-4.3-1.5-4.2-3.3l2-39.6c0.1-1.8,2.1-3.2,4.5-3.2h52.1 c2.4,0,4.3,1.4,4.2,3.2L861.6,655.1z"/>
|
||||||
|
<path class="st1" d="M935.7,655.1c0,1.8-1.9,3.3-4.3,3.3h-53.3c-2.4,0-4.4-1.5-4.3-3.3l0.5-39.6c0-1.8,2-3.2,4.3-3.2h52.1 c2.4,0,4.3,1.4,4.3,3.2L935.7,655.1z"/>
|
||||||
|
<path class="st1" d="M1009.8,655.1c0.1,1.8-1.8,3.3-4.2,3.3h-53.3c-2.4,0-4.4-1.5-4.5-3.3l-0.9-39.6c0-1.8,1.9-3.2,4.2-3.2h52.1 c2.4,0,4.4,1.4,4.5,3.2L1009.8,655.1z"/>
|
||||||
|
<path class="st1" d="M1084,655.1c0.2,1.8-1.7,3.3-4.1,3.3h-53.3c-2.4,0-4.5-1.5-4.6-3.3l-2.3-39.6c-0.1-1.8,1.7-3.2,4.1-3.2h52.1 c2.4,0,4.4,1.4,4.6,3.2L1084,655.1z"/>
|
||||||
|
<path class="st1" d="M1158.1,655.1c0.2,1.8-1.6,3.3-4,3.3h-53.3c-2.4,0-4.5-1.5-4.7-3.3l-3.8-39.6c-0.2-1.8,1.6-3.2,4-3.2h52.1 c2.4,0,4.5,1.4,4.7,3.2L1158.1,655.1z"/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path class="st1" d="M1168.9,612.2c-2.4,0-4.1,1.4-3.9,3.2l5.2,39.6c0.2,1.8,2.4,3.3,4.8,3.3h17.1c2.4,0,4.6,1.5,4.9,3.3 l7.4,51.6c0.3,1.9,2.5,3.5,5,3.5h40.4c2.5,0,4.3-1.6,3.9-3.5l-16.4-97.9c-0.3-1.8-2.5-3.2-4.8-3.2H1168.9z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st1" d="M1176.3,668.1c-2.4,0-6.4,0-8.8,0h-39.9c-2.4,0-4.3,1.5-4.1,3.4l4.5,41.9c0.2,1.9,2.4,3.5,4.9,3.5h40.9 c2.5,0,6.6,0,9,0h4.9c2.5,0,4.3-1.6,4-3.5l-5.8-41.9c-0.3-1.9-2.5-3.4-4.9-3.4H1176.3z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st1" d="M387.2,534.6c-0.4,1.6-2.7,3-4.9,3h-50.2c-2.3,0-3.7-1.3-3.3-3l10.5-35.1c0.5-1.6,2.7-2.8,4.9-2.8h49.1 c2.2,0,3.7,1.3,3.3,2.8L387.2,534.6z"/>
|
||||||
|
<path class="st1" d="M463,534.6c-0.4,1.6-2.5,3-4.8,3H408c-2.3,0-3.8-1.3-3.4-3l9.1-35.1c0.4-1.6,2.6-2.8,4.8-2.8h49.1 c2.2,0,3.8,1.3,3.4,2.8L463,534.6z"/>
|
||||||
|
<path class="st1" d="M538.8,534.6c-0.3,1.6-2.4,3-4.7,3h-50.2c-2.3,0-3.8-1.3-3.5-3l7.7-35.1c0.3-1.6,2.4-2.8,4.7-2.8h49.1 c2.2,0,3.8,1.3,3.5,2.8L538.8,534.6z"/>
|
||||||
|
<path class="st1" d="M614.6,534.6c-0.2,1.6-2.3,3-4.6,3h-50.2c-2.3,0-3.9-1.3-3.6-3l6.3-35.1c0.3-1.6,2.3-2.8,4.6-2.8h49.1 c2.2,0,3.9,1.3,3.6,2.8L614.6,534.6z"/>
|
||||||
|
<path class="st1" d="M691.8,534.6c-0.2,1.6-2.2,3-4.5,3h-50.2c-2.3,0-3.9-1.3-3.7-3l4.9-35.1c0.2-1.6,2.2-2.8,4.4-2.8H692 c2.2,0,3.9,1.3,3.7,2.8L691.8,534.6z"/>
|
||||||
|
<path class="st1" d="M767.6,534.6c-0.1,1.6-2.1,3-4.3,3h-50.2c-2.3,0-4-1.3-3.8-3l3.5-35.1c0.2-1.6,2.1-2.8,4.3-2.8h49.1 c2.2,0,4,1.3,3.8,2.8L767.6,534.6z"/>
|
||||||
|
<path class="st1" d="M843.4,534.6c0,1.6-2,3-4.2,3H789c-2.3,0-4.1-1.3-4-3l2.1-35.1c0.1-1.6,2-2.8,4.2-2.8h49.1c2.2,0,4,1.3,4,2.8 L843.4,534.6z"/>
|
||||||
|
<path class="st1" d="M919.2,534.6c0,1.6-1.8,3-4.1,3H865c-2.3,0-4.1-1.3-4.1-3l0.8-35.1c0-1.6,1.9-2.8,4.1-2.8h49.1 c2.2,0,4.1,1.3,4.1,2.8L919.2,534.6z"/>
|
||||||
|
<path class="st1" d="M996.5,534.6c0.1,1.6-1.7,3-4,3h-50.2c-2.3,0-4.2-1.3-4.2-3l-0.7-35.1c0-1.6,1.8-2.8,4-2.8h49.1 c2.2,0,4.1,1.3,4.2,2.8L996.5,534.6z"/>
|
||||||
|
<path class="st1" d="M1072.3,534.6c0.1,1.6-1.6,3-3.9,3h-50.2c-2.3,0-4.2-1.3-4.3-3l-2-35.1c-0.1-1.6,1.7-2.8,3.9-2.8h49.1 c2.2,0,4.2,1.3,4.3,2.8L1072.3,534.6z"/>
|
||||||
|
<path class="st1" d="M1148.1,534.6c0.2,1.6-1.5,3-3.8,3h-50.2c-2.3,0-4.3-1.3-4.4-3l-3.4-35.1c-0.2-1.6,1.5-2.8,3.8-2.8h49.1 c2.2,0,4.2,1.3,4.4,2.8L1148.1,534.6z"/>
|
||||||
|
<path class="st1" d="M1223.9,534.6c0.3,1.6-1.4,3-3.6,3h-50.2c-2.3,0-4.3-1.3-4.5-3l-4.8-35.1c-0.2-1.6,1.4-2.8,3.7-2.8h49.1 c2.2,0,4.3,1.3,4.5,2.8L1223.9,534.6z"/>
|
||||||
|
<path class="st1" d="M1316.8,534.6c0.4,1.6-1.2,3-3.5,3h-50.2c-2.3,0-4.4-1.3-4.7-3l-6.5-35.1c-0.3-1.6,1.3-2.8,3.5-2.8h49.1 c2.2,0,4.3,1.3,4.7,2.8L1316.8,534.6z"/>
|
||||||
|
<path class="st1" d="M1390.1,534.6c0.4,1.6-1.1,3-3.4,3h-50.2c-2.3,0-4.4-1.3-4.8-3l-7.9-35.1c-0.3-1.6,1.2-2.8,3.4-2.8h49.1 c2.2,0,4.4,1.3,4.8,2.8L1390.1,534.6z"/>
|
||||||
|
<path class="st1" d="M1463.4,534.6c0.5,1.6-1,3-3.3,3h-50.2c-2.3,0-4.5-1.3-4.9-3l-9.2-35.1c-0.4-1.6,1.1-2.8,3.3-2.8h49.1 c2.2,0,4.4,1.3,4.9,2.8L1463.4,534.6z"/>
|
||||||
|
<path class="st1" d="M1330.9,599.7c0.4,1.7-1.2,3.2-3.6,3.2h-51.9c-2.4,0-4.5-1.4-4.9-3.2l-7-37.5c-0.3-1.7,1.3-3,3.6-3h50.7 c2.3,0,4.5,1.4,4.8,3L1330.9,599.7z"/>
|
||||||
|
<path class="st1" d="M1406.6,599.7c0.4,1.7-1.1,3.2-3.5,3.2h-51.9c-2.4,0-4.6-1.4-5-3.2l-8.4-37.5c-0.4-1.7,1.2-3,3.5-3h50.7 c2.3,0,4.5,1.4,5,3L1406.6,599.7z"/>
|
||||||
|
<path class="st1" d="M1482.4,599.7c0.5,1.7-1,3.2-3.4,3.2h-51.9c-2.4,0-4.6-1.4-5.1-3.2l-9.8-37.5c-0.4-1.7,1.1-3,3.4-3h50.7 c2.3,0,4.6,1.4,5.1,3L1482.4,599.7z"/>
|
||||||
|
<path class="st1" d="M1565.1,599.7c0.6,1.7-0.9,3.2-3.2,3.2H1510c-2.4,0-4.7-1.4-5.2-3.2l-11.4-37.5c-0.5-1.7,1-3,3.3-3h50.7 c2.3,0,4.6,1.4,5.2,3L1565.1,599.7z"/>
|
||||||
|
<path class="st1" d="M1637.1,599.7c0.6,1.7-0.8,3.2-3.1,3.2h-51.9c-2.4,0-4.8-1.4-5.3-3.2l-12.8-37.5c-0.6-1.7,0.9-3,3.2-3h50.7 c2.3,0,4.7,1.4,5.3,3L1637.1,599.7z"/>
|
||||||
|
<path class="st1" d="M1709.2,599.7c0.7,1.7-0.6,3.2-3,3.2h-51.9c-2.4,0-4.8-1.4-5.5-3.2l-14.1-37.5c-0.6-1.7,0.7-3,3-3h50.7 c2.3,0,4.7,1.4,5.4,3L1709.2,599.7z"/>
|
||||||
|
<path class="st1" d="M1781.2,599.7c0.8,1.7-0.5,3.2-2.9,3.2h-51.9c-2.4,0-4.9-1.4-5.6-3.2l-15.5-37.5c-0.7-1.7,0.6-3,2.9-3h50.7 c2.3,0,4.8,1.4,5.5,3L1781.2,599.7z"/>
|
||||||
|
<path class="st1" d="M1583.6,655.1c0.6,1.8-0.9,3.3-3.3,3.3H1527c-2.4,0-4.9-1.5-5.4-3.3l-12-39.6c-0.5-1.8,1-3.2,3.3-3.2h52.1 c2.4,0,4.8,1.4,5.4,3.2L1583.6,655.1z"/>
|
||||||
|
<path class="st1" d="M1657.6,655.1c0.7,1.8-0.7,3.3-3.2,3.3h-53.3c-2.4,0-4.9-1.5-5.5-3.3l-13.5-39.6c-0.6-1.8,0.8-3.2,3.2-3.2 h52.1c2.4,0,4.8,1.4,5.5,3.2L1657.6,655.1z"/>
|
||||||
|
<path class="st1" d="M1731.7,655.1c0.7,1.8-0.6,3.3-3,3.3h-53.3c-2.4,0-5-1.5-5.7-3.3l-14.9-39.6c-0.7-1.8,0.7-3.2,3.1-3.2h52.1 c2.4,0,4.9,1.4,5.6,3.2L1731.7,655.1z"/>
|
||||||
|
<path class="st1" d="M1805.7,655.1c0.8,1.8-0.5,3.3-2.9,3.3h-53.3c-2.4,0-5-1.5-5.8-3.3l-16.3-39.6c-0.7-1.8,0.6-3.2,3-3.2h52.1 c2.4,0,4.9,1.4,5.7,3.2L1805.7,655.1z"/>
|
||||||
|
<path class="st1" d="M1603.1,713.7c0.6,1.9-0.9,3.5-3.3,3.5H1545c-2.5,0-5-1.6-5.6-3.5l-12.7-41.9c-0.6-1.9,1-3.4,3.4-3.4h53.6 c2.4,0,4.9,1.5,5.5,3.4L1603.1,713.7z"/>
|
||||||
|
<path class="st1" d="M1679.3,713.7c0.7,1.9-0.7,3.5-3.2,3.5h-54.8c-2.5,0-5.1-1.6-5.7-3.5l-14.2-41.9c-0.6-1.9,0.8-3.4,3.3-3.4 h53.6c2.4,0,5,1.5,5.7,3.4L1679.3,713.7z"/>
|
||||||
|
<path class="st1" d="M1755.5,713.7c0.8,1.9-0.6,3.5-3.1,3.5h-54.8c-2.5,0-5.1-1.6-5.9-3.5l-15.8-41.9c-0.7-1.9,0.7-3.4,3.1-3.4 h53.6c2.4,0,5,1.5,5.8,3.4L1755.5,713.7z"/>
|
||||||
|
<path class="st1" d="M1831.7,713.7c0.9,1.9-0.5,3.5-3,3.5h-54.8c-2.5,0-5.2-1.6-6-3.5l-17.3-41.9c-0.8-1.9,0.6-3.4,3-3.4h53.6 c2.4,0,5.1,1.5,5.9,3.4L1831.7,713.7z"/>
|
||||||
|
<path class="st1" d="M1623.9,775.7c0.7,2.1-0.8,3.7-3.4,3.7H1564c-2.6,0-5.2-1.7-5.8-3.7l-13.5-44.4c-0.6-2,1-3.6,3.5-3.6h55.1 c2.5,0,5.1,1.6,5.7,3.6L1623.9,775.7z"/>
|
||||||
|
<path class="st1" d="M1702.3,775.7c0.8,2.1-0.7,3.7-3.3,3.7h-56.5c-2.6,0-5.2-1.7-5.9-3.7l-15.1-44.4c-0.7-2,0.8-3.6,3.3-3.6h55.1 c2.5,0,5.1,1.6,5.9,3.6L1702.3,775.7z"/>
|
||||||
|
<path class="st1" d="M1780.7,775.7c0.8,2.1-0.6,3.7-3.1,3.7h-56.5c-2.6,0-5.3-1.7-6.1-3.7l-16.7-44.4c-0.7-2,0.7-3.6,3.2-3.6h55.1 c2.5,0,5.2,1.6,6,3.6L1780.7,775.7z"/>
|
||||||
|
<path class="st1" d="M1887.4,839.5c1,2.2-0.4,4-3,4h-58.1c-2.6,0-5.5-1.8-6.4-4l-44.6-108.2c-0.8-2,0.6-3.6,3.1-3.6h55.1 c2.5,0,5.3,1.6,6.1,3.6L1887.4,839.5z"/>
|
||||||
|
<path class="st1" d="M1726.6,841.5c0.8,2.2-0.7,4-3.3,4h-139.1c-2.6,0-5.3-1.8-6-4l-14.3-47.1c-0.6-2.1,1-3.8,3.5-3.8h135.7 c2.6,0,5.3,1.7,6.1,3.8L1726.6,841.5z"/>
|
||||||
|
<path class="st1" d="M1807.4,841.5c0.9,2.2-0.5,4-3.2,4h-58.2c-2.6,0-5.5-1.8-6.3-4l-17.7-47.1c-0.8-2.1,0.7-3.8,3.3-3.8h56.8 c2.6,0,5.4,1.7,6.2,3.8L1807.4,841.5z"/>
|
||||||
|
<path class="st1" d="M1342.8,655.1c0.4,1.8-1.3,3.3-3.7,3.3h-53.3c-2.4,0-4.7-1.5-5-3.3l-7.4-39.6c-0.3-1.8,1.3-3.2,3.7-3.2h52.1 c2.4,0,4.6,1.4,5,3.2L1342.8,655.1z"/>
|
||||||
|
<path class="st1" d="M1420.7,655.1c0.5,1.8-1.1,3.3-3.5,3.3h-53.3c-2.4,0-4.7-1.5-5.1-3.3l-8.9-39.6c-0.4-1.8,1.2-3.2,3.6-3.2 h52.1c2.4,0,4.7,1.4,5.1,3.2L1420.7,655.1z"/>
|
||||||
|
<path class="st1" d="M1498.6,655.1c0.5,1.8-1,3.3-3.4,3.3h-53.3c-2.4,0-4.8-1.5-5.3-3.3l-10.4-39.6c-0.5-1.8,1.1-3.2,3.5-3.2h52.1 c2.4,0,4.7,1.4,5.2,3.2L1498.6,655.1z"/>
|
||||||
|
<path class="st1" d="M1450.9,773.8c0.5,2.1-1.1,3.7-3.7,3.7h-56.4c-2.6,0-5-1.7-5.5-3.7l-9.9-44.3c-0.4-2,1.2-3.6,3.7-3.6h55.1 c2.5,0,4.9,1.6,5.4,3.6L1450.9,773.8z"/>
|
||||||
|
<path class="st1" d="M1382.6,839.5c0.5,2.2-1.3,4-3.9,4h-58.1c-2.6,0-5.1-1.8-5.5-4l-8.7-47c-0.4-2.1,1.4-3.8,4-3.8h56.7 c2.6,0,5,1.7,5.5,3.8L1382.6,839.5z"/>
|
||||||
|
<path class="st1" d="M1467.6,839.5c0.6,2.2-1.1,4-3.8,4h-58.1c-2.6,0-5.2-1.8-5.7-4l-10.5-47c-0.5-2.1,1.3-3.8,3.8-3.8h56.7 c2.6,0,5.1,1.7,5.6,3.8L1467.6,839.5z"/>
|
||||||
|
<path class="st1" d="M1552.5,839.5c0.6,2.2-1,4-3.6,4h-58.1c-2.6,0-5.3-1.8-5.8-4l-12.3-47c-0.5-2.1,1.1-3.8,3.7-3.8h56.7 c2.6,0,5.2,1.7,5.8,3.8L1552.5,839.5z"/>
|
||||||
|
<path class="st1" d="M1556.2,510.6c2.4,7-3.7,12.7-13.6,12.7c-9.9,0-19.8-5.7-22.1-12.7c-2.3-6.9,3.9-12.5,13.6-12.5 C1544,498.1,1553.8,503.7,1556.2,510.6z"/>
|
||||||
|
<path class="st1" d="M1622,510.6c2.6,7-3.2,12.7-13.1,12.7c-9.9,0-20-5.7-22.5-12.7c-2.5-6.9,3.4-12.5,13.2-12.5 C1609.3,498.1,1619.4,503.7,1622,510.6z"/>
|
||||||
|
<path class="st1" d="M1687.8,510.6c2.9,7-2.8,12.7-12.7,12.7c-9.9,0-20.2-5.7-23-12.7c-2.7-6.9,3-12.5,12.8-12.5 C1674.7,498.1,1684.9,503.7,1687.8,510.6z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="hand">
|
||||||
|
<g id="fingers">
|
||||||
|
<path id="thumb" class="st4" d="M1310.4,601.1l-81.9,67.3l-26.4,109.9l57.3,20.3l46.8-90.4l191-30.2l-6-22.8
|
||||||
|
c-13.6-51.5-66.1-82.6-117.9-69.7L1310.4,601.1z"/>
|
||||||
|
<polygon id="pinky" class="st4" points="1348.9,499.2 1242.7,571.9 1270.6,623.2 1230.2,631.3 1176.4,574.6 1253.5,432.3
|
||||||
|
1402,477.5 "/>
|
||||||
|
<polygon id="ring" class="st4" points="1374.8,415 1139.1,535 1133.8,619.7 1139.7,686.1 1186.8,680.6 1194.3,584.9 1246.6,510
|
||||||
|
"/>
|
||||||
|
<polygon id="middle" class="st4" points="1232.9,425.7 1125.5,494.3 1068.4,584.8 1053.5,719.1 1104.7,728.8 1135.6,609.3
|
||||||
|
1202,520.5 1384.2,445.9 "/>
|
||||||
|
<path id="index" class="st4" d="M1298.2,407.4l-176.7-53.8l-111.3,103.1l-5.3,123.7l48.2,5.8l24.2-91.7l55.9-41.8l120.1,65.1 l39.4-14.3c25.8-9.4,37.1-39.7,23.6-63.6L1298.2,407.4z"/>
|
||||||
|
</g>
|
||||||
|
<path id="arm" class="st4" d="M1497.2,678.1L1657,577.6l47.7-67.4l287.7-287.5l-181.6-84.6l-201.1,246.2l-311.6,23l-26.7,7.1 c-33.2,8.9-49.3,46.6-32.8,76.7l14.7,26.8l56.9,83.2l33.2,55.8L1497.2,678.1z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
svg {
|
||||||
|
width: 80vw;
|
||||||
|
height: 40vw;
|
||||||
|
overflow: visible;
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
width: 60vw;
|
||||||
|
height: 30vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#hand {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
#keys path {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.st0{fill:var(--color-bg);}
|
||||||
|
.st1{fill:var(--color-text)}
|
||||||
|
.st4{fill:var(--color-highlight, #000);}
|
||||||
|
</style>
|
||||||
21
src/lib/components/HomeIlluShape.svelte
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<svg class="shape" x="0px" y="0px" viewBox="0 0 1000 1000" width="1000" height="1000">
|
||||||
|
<path class="morphshape" d="M1000,0 C1000,333.33333 1000,666.66667 1000,1000 666.66667,1000 333.33333,1000 0,1000 0,666.66667 0,333.33333 0,0 333.33333,0 666.66667,0 1000,0 z"/>
|
||||||
|
<circle class="sphere" cx="500" cy="500" r="500"/>
|
||||||
|
<path class="quartercirc" d="M0,0c0,552.3,447.7,1000,1000,1000V0L0,0z"/>
|
||||||
|
<polygon class="triangle" points="0,1000 0,0 1000,0 "/>
|
||||||
|
<rect class="rectangle" x="0" y="0" width="1000" height="1000"/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.shape {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
}
|
||||||
|
.shape > * {
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
}
|
||||||
|
.sphere, .quartercirc, .triangle, .rectangle {
|
||||||
|
fill: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
After Width: | Height: | Size: 744 B |
88
src/lib/components/HomeIlluShapes.svelte
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import HomeIlluShape from "./HomeIlluShape.svelte";
|
||||||
|
import gsap from "gsap";
|
||||||
|
import MorphSVGPlugin from "gsap/dist/MorphSVGPlugin";
|
||||||
|
import ScrollTrigger from "gsap/dist/ScrollTrigger";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
onMount( () => {
|
||||||
|
gsap.registerPlugin(MorphSVGPlugin, ScrollTrigger);
|
||||||
|
|
||||||
|
let introTl = gsap.timeline({
|
||||||
|
scrollTrigger: {
|
||||||
|
trigger: '.home-illu-shapes',
|
||||||
|
start: 'top 80%',
|
||||||
|
end: 'top 0%',
|
||||||
|
scrub: false,
|
||||||
|
// markers: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.querySelectorAll('.home-illu-shapes > .shape').forEach( (shape) => {
|
||||||
|
introTl.fromTo(shape,
|
||||||
|
{ autoAlpha: 0, x: Math.random() * 1000 - 500, y: Math.random() * 1000 - 500},
|
||||||
|
{ autoAlpha: 1, x: 0, y: 0, duration: 1, ease: "cubic.inOut" }, 0
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
let shapesToPaths = MorphSVGPlugin.convertToPath('.sphere, .quartercirc, .triangle, .rectangle');
|
||||||
|
let shapes = [shapesToPaths[0], shapesToPaths[1], shapesToPaths[2], shapesToPaths[3]]
|
||||||
|
|
||||||
|
const generateAngle = () => {
|
||||||
|
let rand = Math.floor(Math.random() * 2);
|
||||||
|
return rand === 0 ? 90 : -90;
|
||||||
|
}
|
||||||
|
|
||||||
|
const randomMorph = (shape: HTMLElement, index: number = 0) => {
|
||||||
|
const randomShape = shapes[Math.floor(Math.random() * shapes.length)];
|
||||||
|
|
||||||
|
let rowindex = (index: number) => {
|
||||||
|
// based on the index of an element within an array of 5x3 grid, return the columns index, so for example 0, 5 and 10 would return 0, index 1, 6 and 11 would return 1, etc
|
||||||
|
return index % 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
gsap.to(shape, {
|
||||||
|
duration: 1,
|
||||||
|
rotationZ: "+=" + generateAngle(),
|
||||||
|
morphSVG: randomShape,
|
||||||
|
ease: 'power4.out',
|
||||||
|
delay: rowindex(index) * 0.1,
|
||||||
|
onComplete: () => { setTimeout( () => randomMorph(shape), 2000 ) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll('.morphshape').forEach( (shape, index) => {
|
||||||
|
randomMorph(shape as HTMLElement, index);
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="home-illu-shapes">
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
<HomeIlluShape />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.home-illu-shapes {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
:global(.home-illu-shapes > *) {
|
||||||
|
flex-basis: calc(20% - 5px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
<svg id="floter-logo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 287.4 83.5" width="290" height="85">
|
<script lang="ts">
|
||||||
|
import { logotext } from "$lib/utils/stores";
|
||||||
|
|
||||||
|
// let $logotexttext = logotext.subscribe((value) => JSON.stringify(value));
|
||||||
|
</script>
|
||||||
|
<!-- <svg id="floter-logo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 287.4 83.5" width="290" height="85">
|
||||||
<path id="r" d="M259.9 82.4h-24.2l11.6-54.9h22l-2.7 12.9c4.5-8.9 11-14 18.1-14 1 0 2.1 0 2.7.2l-4.7 22.1c-1.4-.4-3.3-.9-6.4-.9-5.4 0-9.7 2.3-10.8 7.7l-5.6 26.9z"/>
|
<path id="r" d="M259.9 82.4h-24.2l11.6-54.9h22l-2.7 12.9c4.5-8.9 11-14 18.1-14 1 0 2.1 0 2.7.2l-4.7 22.1c-1.4-.4-3.3-.9-6.4-.9-5.4 0-9.7 2.3-10.8 7.7l-5.6 26.9z"/>
|
||||||
<path id="e" d="M237.9 59.3h-35.7c.3 5.2 2.2 7.5 6.5 7.5 2.9 0 5.1-1.5 5.9-4.2h22.3c-4.3 13.2-14.5 20.9-30.4 20.9-16.3 0-26.5-9.7-26.5-25.2 0-17.8 13.4-32 32.3-32 16.3 0 26.5 9.7 26.5 25.2 0 2.7-.4 5.3-.9 7.8zM203.3 50h13.5c-.2-4-1.8-6.5-6-6.5-3.4 0-6.1 2.1-7.5 6.5z"/>
|
<path id="e" d="M237.9 59.3h-35.7c.3 5.2 2.2 7.5 6.5 7.5 2.9 0 5.1-1.5 5.9-4.2h22.3c-4.3 13.2-14.5 20.9-30.4 20.9-16.3 0-26.5-9.7-26.5-25.2 0-17.8 13.4-32 32.3-32 16.3 0 26.5 9.7 26.5 25.2 0 2.7-.4 5.3-.9 7.8zM203.3 50h13.5c-.2-4-1.8-6.5-6-6.5-3.4 0-6.1 2.1-7.5 6.5z"/>
|
||||||
<path id="t" d="M171.5 65.9c1.9 0 4.3-.3 6.3-1L174 82.2c-2.5.8-7.1 1.3-11.1 1.3-14 0-23.2-5.1-19.6-22.3l3.5-16.7h-5.5l3.6-17h5.5l3.3-15.4H178l-3.3 15.4h11l-3.6 17h-11l-3.3 15.8c-.9 3.9.3 5.6 3.7 5.6z"/>
|
<path id="t" d="M171.5 65.9c1.9 0 4.3-.3 6.3-1L174 82.2c-2.5.8-7.1 1.3-11.1 1.3-14 0-23.2-5.1-19.6-22.3l3.5-16.7h-5.5l3.6-17h5.5l3.3-15.4H178l-3.3 15.4h11l-3.6 17h-11l-3.3 15.8c-.9 3.9.3 5.6 3.7 5.6z"/>
|
||||||
|
|
@ -6,13 +11,25 @@
|
||||||
<path id="o" d="M111.4 26.4c16.7 0 27.2 9.7 27.2 25.2 0 17.8-13.7 32-33.1 32-16.7 0-27.2-9.7-27.2-25.2 0-17.9 13.8-32 33.1-32zm-3.9 36.7c5.3 0 8.8-4.3 8.8-9.4 0-4.2-2.5-6.8-6.6-6.8-5.4 0-8.9 4.3-8.9 9.4 0 4.1 2.5 6.8 6.7 6.8z"/>
|
<path id="o" d="M111.4 26.4c16.7 0 27.2 9.7 27.2 25.2 0 17.8-13.7 32-33.1 32-16.7 0-27.2-9.7-27.2-25.2 0-17.9 13.8-32 33.1-32zm-3.9 36.7c5.3 0 8.8-4.3 8.8-9.4 0-4.2-2.5-6.8-6.6-6.8-5.4 0-8.9 4.3-8.9 9.4 0 4.1 2.5 6.8 6.7 6.8z"/>
|
||||||
<polygon id="l" points="45.5,82.4 63,0 87.1,0 69.7,82.4"/>
|
<polygon id="l" points="45.5,82.4 63,0 87.1,0 69.7,82.4"/>
|
||||||
<polygon id="F" points="17.5,0 59.7,0 55.5,19.8 36.9,19.8 34.1,33 50.5,33 46.3,52.7 29.9,52.7 23.6,82.4 0,82.4"/>
|
<polygon id="F" points="17.5,0 59.7,0 55.5,19.8 36.9,19.8 34.1,33 50.5,33 46.3,52.7 29.9,52.7 23.6,82.4 0,82.4"/>
|
||||||
</svg>
|
</svg> -->
|
||||||
|
<div id="floter-logo">{$logotext}</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#floter-logo {
|
/* #floter-logo {
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: auto;
|
width: auto;
|
||||||
display: block;
|
display: block;
|
||||||
|
} */
|
||||||
|
#floter-logo {
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
font-size: 36px;
|
||||||
|
letter-spacing: -0.033em;
|
||||||
|
line-height: 36px;
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang='ts'>
|
<script lang='ts'>
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { gsap } from "gsap";
|
import { gsap } from "gsap";
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
|
||||||
|
|
@ -15,6 +16,9 @@
|
||||||
let navlinks = document.querySelectorAll('nav a');
|
let navlinks = document.querySelectorAll('nav a');
|
||||||
navlinks.forEach((link, index) => {
|
navlinks.forEach((link, index) => {
|
||||||
link.addEventListener('click', (e)=> {
|
link.addEventListener('click', (e)=> {
|
||||||
|
if (e.target?.toString() === $page.url.toString()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const checkbox = document.querySelector('input[type="checkbox"]') as HTMLInputElement;
|
const checkbox = document.querySelector('input[type="checkbox"]') as HTMLInputElement;
|
||||||
checkbox ? checkbox.checked = false : null;
|
checkbox ? checkbox.checked = false : null;
|
||||||
gsap.to('.content > *', {duration: 0.5, y: '100%', autoAlpha: 1, ease: 'power4.out'});
|
gsap.to('.content > *', {duration: 0.5, y: '100%', autoAlpha: 1, ease: 'power4.out'});
|
||||||
|
|
@ -48,9 +52,9 @@
|
||||||
<span class="close">×</span>
|
<span class="close">×</span>
|
||||||
</label>
|
</label>
|
||||||
<nav id="nav">
|
<nav id="nav">
|
||||||
<a href="/">Home</a>
|
<a href="/" class="navlink {$page.route.id === '/' ? 'current' : ''}">Home</a>
|
||||||
<a href="/work">About</a>
|
<a href="/about" class="navlink {$page.route.id === '/about' ? 'current' : ''}">About</a>
|
||||||
<a href="/work">Hire</a>
|
<a href="/work" class="navlink {$page.route.id === '/work' ? 'current' : ''}">Work</a>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
@ -122,5 +126,9 @@
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.current {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -13,24 +13,30 @@ import { tick } from 'svelte';
|
||||||
|
|
||||||
export let textsToCanvas: Array<HTMLElement> = [];
|
export let textsToCanvas: Array<HTMLElement> = [];
|
||||||
export let imgsToCanvas: Array<HTMLElement> = [];
|
export let imgsToCanvas: Array<HTMLElement> = [];
|
||||||
export let bulgeFactor: number = 0.15;
|
export let bulgeFactor: number = 0.15; // comes from attribute
|
||||||
let app: PIXI.Application;
|
let app: PIXI.Application;
|
||||||
let canvas: HTMLCanvasElement;
|
let canvas: HTMLCanvasElement;
|
||||||
|
|
||||||
onMount(()=>{
|
onMount( () => {
|
||||||
|
|
||||||
let is_fine = window.matchMedia('(pointer:fine)').matches
|
let is_fine = window.matchMedia('(pointer:fine)').matches
|
||||||
let is_landscape = window.matchMedia('(orientation:landscape)').matches
|
let is_landscape = window.matchMedia('(orientation:landscape)').matches
|
||||||
|
|
||||||
gsap.registerPlugin(PixiPlugin, ScrollTrigger, SplitText);
|
gsap.registerPlugin(PixiPlugin, ScrollTrigger, SplitText);
|
||||||
|
|
||||||
|
const root = document.querySelector(':root') as HTMLElement;
|
||||||
|
const bgColorFromRoot = () => { return getComputedStyle(root).getPropertyValue('--color-bg') || 'rgb(255, 255, 255)'};
|
||||||
|
function textColorFromRoot(){ return getComputedStyle(root).getPropertyValue('--color-text') || 'rgb(0, 0, 0)' };
|
||||||
|
const highlightColorFromRoot = () => { return getComputedStyle(root).getPropertyValue('--color-highlight') || 'rgb(0, 0, 0)' };
|
||||||
|
const thisElemBgColor = (elem: HTMLElement) => { return getComputedStyle(elem).getPropertyValue('background-color') || 'rgb(255, 255, 255)' };
|
||||||
|
|
||||||
app = new PIXI.Application({
|
app = new PIXI.Application({
|
||||||
resizeTo: window,
|
resizeTo: window,
|
||||||
antialias: true,
|
antialias: true,
|
||||||
autoDensity: true,
|
autoDensity: true,
|
||||||
resolution: 2,
|
resolution: 2,
|
||||||
backgroundAlpha: 1,
|
backgroundColor: bgColorFromRoot(),
|
||||||
backgroundColor: 0x223ad4,
|
backgroundAlpha: 0,
|
||||||
view: canvas,
|
view: canvas,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -52,15 +58,19 @@ onMount(()=>{
|
||||||
group.y = window.innerHeight / 2;
|
group.y = window.innerHeight / 2;
|
||||||
app.stage.addChild(group);
|
app.stage.addChild(group);
|
||||||
|
|
||||||
let recty = new PIXI.Graphics();
|
let group_background = new PIXI.Graphics();
|
||||||
recty.beginFill('rgb(0, 0, 0)');
|
function draw_group_background(group_background: PIXI.Graphics) {
|
||||||
recty.drawRect(0, 0, xFrac(1), yFrac(1));
|
group_background.clear();
|
||||||
recty.endFill();
|
group_background.beginFill(bgColorFromRoot());
|
||||||
recty.alpha = 0;
|
group_background.drawRect(0, 0, xFrac(1), yFrac(1));
|
||||||
recty.pivot.set(xFrac(.5), yFrac(.5));
|
group_background.endFill();
|
||||||
recty.x = xFrac(0.5);
|
group_background.alpha = 0;
|
||||||
recty.y = yFrac(0.5);
|
group_background.pivot.set(xFrac(.5), yFrac(.5));
|
||||||
group.addChild(recty);
|
group_background.x = xFrac(0.5);
|
||||||
|
group_background.y = yFrac(0.5);
|
||||||
|
}
|
||||||
|
draw_group_background(group_background);
|
||||||
|
group.addChild(group_background);
|
||||||
|
|
||||||
let center = [0.5, 0.5];
|
let center = [0.5, 0.5];
|
||||||
let bulgefilter = new BulgePinchFilter();
|
let bulgefilter = new BulgePinchFilter();
|
||||||
|
|
@ -68,8 +78,9 @@ onMount(()=>{
|
||||||
bulgefilter.strength = is_landscape ? bulgeFactor : bulgeFactor * 1.25;
|
bulgefilter.strength = is_landscape ? bulgeFactor : bulgeFactor * 1.25;
|
||||||
bulgefilter.center = center;
|
bulgefilter.center = center;
|
||||||
bulgefilter.resolution = 2;
|
bulgefilter.resolution = 2;
|
||||||
app.stage.filters = [bulgefilter];
|
|
||||||
|
|
||||||
|
app.stage.filters = [bulgefilter];
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------
|
/*----------------------------------
|
||||||
* Convert text to canvas using
|
* Convert text to canvas using
|
||||||
|
|
@ -87,7 +98,6 @@ onMount(()=>{
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------
|
/*----------------------------------
|
||||||
* Function to update text on canvas
|
* Function to update text on canvas
|
||||||
* runs in the Ticker
|
* runs in the Ticker
|
||||||
|
|
@ -95,11 +105,11 @@ onMount(()=>{
|
||||||
function updateText(){
|
function updateText(){
|
||||||
canvasTexts.forEach((text, index) => {
|
canvasTexts.forEach((text, index) => {
|
||||||
let headlinePosition = elems[index].getBoundingClientRect();
|
let headlinePosition = elems[index].getBoundingClientRect();
|
||||||
text.position.set(headlinePosition.x, headlinePosition.y);
|
text.position.set(headlinePosition.x - ((tween.x - 0.5) * 50), headlinePosition.y - ((tween.y - 0.5) * 50));
|
||||||
// text.position.x = headlinePosition.x;
|
text.alpha = window.getComputedStyle(elems[index]).opacity as unknown as number;
|
||||||
// ^ This bcs pos:fixed doesn't update fast enough when mobile browser chrome changes on scroll
|
text.style.fill = window.getComputedStyle(elems[index]).color;
|
||||||
text.alpha = elems[index].style.opacity as unknown as number || 0.3;
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------
|
/*----------------------------------
|
||||||
|
|
@ -112,7 +122,7 @@ onMount(()=>{
|
||||||
function convertImgs(){
|
function convertImgs(){
|
||||||
imgsToCanvas.forEach((element) => {
|
imgsToCanvas.forEach((element) => {
|
||||||
imgElems.push(element);
|
imgElems.push(element);
|
||||||
let canvasImg = createCanvasImg(element as HTMLImageElement, app.stage);
|
let canvasImg = createCanvasImg(element as HTMLImageElement, group);
|
||||||
canvasImgs.push(canvasImg);
|
canvasImgs.push(canvasImg);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -122,6 +132,7 @@ onMount(()=>{
|
||||||
* Function to update text on canvas
|
* Function to update text on canvas
|
||||||
* runs in the Ticker
|
* runs in the Ticker
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
|
|
||||||
function updateImgs(){
|
function updateImgs(){
|
||||||
canvasImgs.forEach((image, index) => {
|
canvasImgs.forEach((image, index) => {
|
||||||
let imagePosition = imgElems[index].getBoundingClientRect();
|
let imagePosition = imgElems[index].getBoundingClientRect();
|
||||||
|
|
@ -133,7 +144,44 @@ onMount(()=>{
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let workinfoBgs: Array<PIXI.Graphics> = [];
|
||||||
|
let workinfos = document.querySelectorAll('.work-info');
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------
|
||||||
|
* Create background for workinfo
|
||||||
|
----------------------------------*/
|
||||||
|
function createWorkInfoBgs() {
|
||||||
|
workinfos.forEach( workinfo => {
|
||||||
|
const workinfoRect = workinfo.getBoundingClientRect();
|
||||||
|
let workinfoGraphic = new PIXI.Graphics();
|
||||||
|
workinfoGraphic.beginFill(textColorFromRoot());
|
||||||
|
workinfoGraphic.drawRect(workinfoRect.x, workinfoRect.y, workinfoRect.width, workinfoRect.height);
|
||||||
|
workinfoGraphic.endFill();
|
||||||
|
workinfoGraphic.pivot.set(workinfoRect.x, workinfoRect.y);
|
||||||
|
workinfoBgs.push(workinfoGraphic);
|
||||||
|
app.stage.addChild(workinfoGraphic);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------
|
||||||
|
* Update background for workinfo
|
||||||
|
----------------------------------*/
|
||||||
|
function updateWorkInfoBgs() {
|
||||||
|
workinfos.forEach((workinfo, index) => {
|
||||||
|
const workinfoRect = workinfo.getBoundingClientRect();
|
||||||
|
workinfoBgs[index].clear();
|
||||||
|
workinfoBgs[index].beginFill(thisElemBgColor(workinfo as HTMLElement));
|
||||||
|
workinfoBgs[index].drawRect(workinfoRect.x, workinfoRect.y, workinfoRect.width, workinfoRect.height);
|
||||||
|
workinfoBgs[index].endFill();
|
||||||
|
workinfoBgs[index].pivot.set(workinfoRect.x, workinfoRect.y);
|
||||||
|
workinfoBgs[index].position.set(workinfoRect.x - ((tween.x - 0.5) * 50), workinfoRect.y - ((tween.y - 0.5) * 50));
|
||||||
|
workinfoBgs[index].alpha = window.getComputedStyle(workinfo).opacity as unknown as number;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
createWorkInfoBgs();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
convertImgs();
|
convertImgs();
|
||||||
convertText();
|
convertText();
|
||||||
|
|
@ -177,6 +225,7 @@ onMount(()=>{
|
||||||
bulgefilter.strength = is_landscape ? bulgeFactor : bulgeFactor * 1.25;
|
bulgefilter.strength = is_landscape ? bulgeFactor : bulgeFactor * 1.25;
|
||||||
updateImgs();
|
updateImgs();
|
||||||
updateText();
|
updateText();
|
||||||
|
updateWorkInfoBgs();
|
||||||
})
|
})
|
||||||
}) // <- end onMount
|
}) // <- end onMount
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ type Post = {
|
||||||
header_bg_image: string
|
header_bg_image: string
|
||||||
svg: string
|
svg: string
|
||||||
video: string
|
video: string
|
||||||
|
order: number
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
render: () => string
|
render: () => string
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
:root {
|
:root {
|
||||||
--spacing-outer: 5vw;
|
--spacing-outer: 5vw;
|
||||||
--spacing-nav: 5vw;
|
--spacing-nav: 5vw;
|
||||||
// --color-bg: #FFF;
|
--color-bg: #3c71c8;
|
||||||
// --color-text: #000;
|
--color-text: #ffeee6;
|
||||||
// --color-bg: #00117f;
|
--color-highlight: #000000;
|
||||||
--color-bg: #223ad4;
|
// --color-bg: #000000;
|
||||||
// --color-text: #FF9494;
|
// --color-text: #FFFFFF;
|
||||||
--color-text: #FFF;
|
// --color-highlight: #FF4D00;
|
||||||
--aspect-ratio-heroes: 1.5;
|
--aspect-ratio-heroes: 1.5;
|
||||||
--font-size-p: clamp(20px, 1.6vw, 1.6vw);
|
--font-size-p: clamp(20px, 1.6vw, 1.6vw);
|
||||||
|
|
||||||
|
|
@ -30,17 +30,34 @@ body {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
min-height: 100svh;
|
min-height: 100svh;
|
||||||
}
|
}
|
||||||
|
// body:after {
|
||||||
|
// content: '';
|
||||||
|
// display: block;
|
||||||
|
// position: fixed;
|
||||||
|
// top: 0;
|
||||||
|
// left: 0;
|
||||||
|
// width: calc(100vw - 00px);
|
||||||
|
// height: calc(100svh - 30px);
|
||||||
|
// border: 15px solid var(--color-text);
|
||||||
|
// z-index: 1;
|
||||||
|
// pointer-events: none;
|
||||||
|
// }
|
||||||
body * {
|
body * {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
h1, h2, h3, h4, h5 {
|
h1, h2, h3, h4, h5 {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
line-height: 1.2;
|
line-height: 1.1;
|
||||||
font-weight: 900;
|
font-weight: 400;
|
||||||
font-style: italic;
|
letter-spacing: -0.025em;
|
||||||
letter-spacing: -0.02em;
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 3.5em;
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
ul, ol {
|
ul, ol {
|
||||||
|
|
@ -57,12 +74,14 @@ p, li {
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
.button {
|
.cta {
|
||||||
font-size: clamp(20px, 1.6vw, 1.6vw);
|
font-size: clamp(20px, 1.6vw, 1.6vw);
|
||||||
|
}
|
||||||
|
.button {
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 1em 0.5em 1em 0;
|
margin: 1em 0.125em;
|
||||||
padding: .75em;
|
padding: .75em;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
@ -71,38 +90,37 @@ a {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
letter-spacing: -0.01em;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
letter-spacing: 0.01em;
|
font-size: clamp(21px, 1.7vw, 1.7vw);
|
||||||
}
|
}
|
||||||
&:before {
|
&:before {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
left: 0px;
|
||||||
|
bottom: 0;
|
||||||
border: 2px solid var(--color-text);
|
border: 2px solid var(--color-text);
|
||||||
border-radius: 0;
|
background-color: var(--color-bg);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
}
|
}
|
||||||
&:hover:before {
|
&:hover:before {
|
||||||
left: -10px;
|
width: 100%;
|
||||||
width: calc(100% + 20px);
|
height: calc(100% + 10px);
|
||||||
height: calc(100% - 10px);
|
left: 0;
|
||||||
bottom: 5px;
|
bottom: -5px;
|
||||||
border-radius: .25em;
|
|
||||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
}
|
}
|
||||||
&.button--primary {
|
&.button--primary {
|
||||||
color: var(--color-bg);
|
color: var(--color-bg);
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
background-color: var(--color-text);
|
background-color: var(--color-highlight);
|
||||||
|
border: 2px solid var(--color-highlight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.button--xl {
|
&.button--xl {
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,25 @@ export default function createCanvasText( element: HTMLImageElement, stage: PIX
|
||||||
const elem = element;
|
const elem = element;
|
||||||
const elemSrc = elem.currentSrc || elem.src;
|
const elemSrc = elem.currentSrc || elem.src;
|
||||||
const elemPosition = elem.getBoundingClientRect();
|
const elemPosition = elem.getBoundingClientRect();
|
||||||
|
let canvasImg: PIXI.Sprite;
|
||||||
|
let scalefactor = 1;
|
||||||
|
|
||||||
|
if (elemSrc.includes('.svg')) {
|
||||||
|
scalefactor = Number(elem.attributes.getNamedItem('data-svgscale')?.value);
|
||||||
|
const canvasImgTexture = PIXI.Texture.from(elemSrc, { resourceOptions: { scale: scalefactor } });
|
||||||
|
canvasImg = new PIXI.Sprite(canvasImgTexture);
|
||||||
|
} else {
|
||||||
|
canvasImg = PIXI.Sprite.from(elemSrc);
|
||||||
|
}
|
||||||
|
|
||||||
const canvasImg = PIXI.Sprite.from(elemSrc);
|
|
||||||
canvasImg.position.set(elemPosition.x, elemPosition.y);
|
canvasImg.position.set(elemPosition.x, elemPosition.y);
|
||||||
canvasImg.width = elemPosition.width;
|
canvasImg.width = elemPosition.width/scalefactor;
|
||||||
canvasImg.height = elemPosition.height;
|
canvasImg.height = elemPosition.height;
|
||||||
canvasImg.on('added', () => {
|
canvasImg.on('added', () => {
|
||||||
console.log('canvas imgs added');
|
|
||||||
elem.classList.add('canvas-img-added');
|
elem.classList.add('canvas-img-added');
|
||||||
elem.style.visibility = 'hidden';
|
elem.style.visibility = 'hidden';
|
||||||
});
|
});
|
||||||
stage.addChild(canvasImg);
|
stage.addChild(canvasImg);
|
||||||
|
|
||||||
// elem.style.opacity = '0';
|
|
||||||
return canvasImg;
|
return canvasImg;
|
||||||
}
|
}
|
||||||
|
|
@ -9,12 +9,16 @@ export default function createCanvasText( element: HTMLElement, stage: PIXI.Con
|
||||||
const elemFontWeight = elemStyles.getPropertyValue('font-weight') || 'normal';
|
const elemFontWeight = elemStyles.getPropertyValue('font-weight') || 'normal';
|
||||||
const elemFontFamily = elemStyles.getPropertyValue('font-family') || 'Arial';
|
const elemFontFamily = elemStyles.getPropertyValue('font-family') || 'Arial';
|
||||||
const elemFontStyle = elemStyles.getPropertyValue('font-style') || 'normal';
|
const elemFontStyle = elemStyles.getPropertyValue('font-style') || 'normal';
|
||||||
const elemLetterSpacing = parseInt(elemStyles.getPropertyValue('letter-spacing')) || 0;
|
const elemLetterSpacing = Number(elemStyles.getPropertyValue('letter-spacing').replace('px','')) || 0;
|
||||||
const elemColor = elemStyles.getPropertyValue('color') || 'black';
|
const elemColor = elemStyles.getPropertyValue('color') || 'black';
|
||||||
const elemAlignment = elemStyles.getPropertyValue('text-align') || 'left';
|
const elemAlignment = elemStyles.getPropertyValue('text-align') || 'left';
|
||||||
|
|
||||||
const elemPosition = elem.getBoundingClientRect();
|
const elemPosition = elem.getBoundingClientRect();
|
||||||
const canvasText = new Text(elem?.textContent as string, {
|
const elemTextTransform = elemStyles.getPropertyValue('text-transform') || 'none';
|
||||||
|
if (elemTextTransform === 'uppercase') {
|
||||||
|
elem.textContent = elem.textContent?.toUpperCase() as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvasText = new Text(elem.textContent as string, {
|
||||||
fontFamily: elemFontFamily,
|
fontFamily: elemFontFamily,
|
||||||
fontSize: elemFontSize,
|
fontSize: elemFontSize,
|
||||||
fontWeight: elemFontWeight as PIXI.TextStyleFontWeight,
|
fontWeight: elemFontWeight as PIXI.TextStyleFontWeight,
|
||||||
|
|
@ -22,16 +26,15 @@ export default function createCanvasText( element: HTMLElement, stage: PIXI.Con
|
||||||
letterSpacing: elemLetterSpacing,
|
letterSpacing: elemLetterSpacing,
|
||||||
fill: elemColor,
|
fill: elemColor,
|
||||||
align: elemAlignment as PIXI.TextStyleAlign,
|
align: elemAlignment as PIXI.TextStyleAlign,
|
||||||
|
padding: 20,
|
||||||
});
|
});
|
||||||
|
|
||||||
canvasText.on('added', () => {
|
canvasText.on('added', () => {
|
||||||
console.log('canvas text added');
|
|
||||||
elem.classList.add('canvas-text-added');
|
elem.classList.add('canvas-text-added');
|
||||||
elem.style.opacity = '0';
|
|
||||||
elem.style.visibility = 'hidden';
|
elem.style.visibility = 'hidden';
|
||||||
});
|
});
|
||||||
canvasText.position.set(elemPosition.x, elemPosition.y);
|
canvasText.position.set(elemPosition.x, elemPosition.y);
|
||||||
// canvasText.zIndex = 100;
|
|
||||||
stage.addChild(canvasText);
|
stage.addChild(canvasText);
|
||||||
|
|
||||||
return canvasText;
|
return canvasText
|
||||||
}
|
}
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
import sharp from 'sharp';
|
|
||||||
|
|
||||||
export const IMAGE_DIR='/src/lib/assets/';
|
|
||||||
|
|
||||||
export async function dominantColour({ source }: { source: string }){
|
|
||||||
try {
|
|
||||||
const image = sharp(source);
|
|
||||||
const{ dominant }=await image.stats();
|
|
||||||
return dominant;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error determining dominant colour: ', source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function lowResolutionPlaceholder({ source }: { source: string }) {
|
|
||||||
try {
|
|
||||||
const image = sharp(source);
|
|
||||||
const buffer = await image
|
|
||||||
.resize(10)
|
|
||||||
.jpeg({
|
|
||||||
quality: 50,
|
|
||||||
progressive: true,
|
|
||||||
optimiseScans: true,
|
|
||||||
chromaSubsampling: '4:2:0',
|
|
||||||
trellisQuantisation: true,
|
|
||||||
quantisationTable: 2,
|
|
||||||
})
|
|
||||||
.toBuffer({ resolveWithObject: false });
|
|
||||||
return `data:image/jpeg;base64,${(await buffer).toString('base64')}`;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error generating low resolution placeholder: ', source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export const dominantColourPlaceholder = async ({ source }: {source: string})=>{
|
|
||||||
try{
|
|
||||||
const dominant = await dominantColour({ source }) as { r: number; g: number; b: number };
|
|
||||||
const{ r, g, b }= dominant;
|
|
||||||
const buffer = await sharp({
|
|
||||||
create:{
|
|
||||||
width:3,
|
|
||||||
height:2,
|
|
||||||
channels:3,
|
|
||||||
background:{ r, g, b },
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.jpeg()
|
|
||||||
.toBuffer({resolveWithObject:false});
|
|
||||||
return`data:image/jpeg;base64,${buffer.toString('base64')}`;
|
|
||||||
}catch(error){
|
|
||||||
console.error('Error determining dominant colour: ', source);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
45
src/lib/utils/rgbToHex.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
function hslToHex(h:number, s:number, l:number) {
|
||||||
|
l /= 100;
|
||||||
|
const a = s * Math.min(l, 1 - l) / 100;
|
||||||
|
const f = (n:number) => {
|
||||||
|
const k = (n + h / 30) % 12;
|
||||||
|
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
||||||
|
return Math.round(255 * color).toString(16).padStart(2, '0'); // convert to Hex and prefix "0" if needed
|
||||||
|
};
|
||||||
|
return `0x${f(0)}${f(8)}${f(4)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RGBToHex(colorstring: string) {
|
||||||
|
if (colorstring.charAt(0) == "#"){
|
||||||
|
colorstring = colorstring.replace("#", "0x");
|
||||||
|
return colorstring;
|
||||||
|
}
|
||||||
|
if (colorstring.charAt(0) == "r") {
|
||||||
|
// Choose correct separator
|
||||||
|
const sep = colorstring.indexOf(",") > -1 ? "," : " ";
|
||||||
|
// Turn "rgb(r,g,b)" into [r,g,b]
|
||||||
|
const rgbArray = colorstring.substr(4).split(")")[0].split(sep);
|
||||||
|
|
||||||
|
let r = (+rgbArray[0]).toString(16),
|
||||||
|
g = (+rgbArray[1]).toString(16),
|
||||||
|
b = (+rgbArray[2]).toString(16);
|
||||||
|
|
||||||
|
if (r.length == 1)
|
||||||
|
r = "0" + r;
|
||||||
|
if (g.length == 1)
|
||||||
|
g = "0" + g;
|
||||||
|
if (b.length == 1)
|
||||||
|
b = "0" + b;
|
||||||
|
|
||||||
|
return "0x" + r + g + b;
|
||||||
|
}
|
||||||
|
if (colorstring.charAt(0) == "h") {
|
||||||
|
|
||||||
|
const hslArray = colorstring.substr(4).split(")")[0].split(",");
|
||||||
|
const h = Number(hslArray[0]);
|
||||||
|
const s = Number(hslArray[1].replace("%", ""));
|
||||||
|
const l = Number(hslArray[2].replace("%", ""));
|
||||||
|
|
||||||
|
return hslToHex(h, s, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
export const workbulge = writable(0.25);
|
export const workbulge = writable(0.25);
|
||||||
export const loading = writable(false);
|
export const loading = writable(false);
|
||||||
|
export const logotext = writable('Flöter');
|
||||||
|
|
@ -5,10 +5,13 @@
|
||||||
import { gsap } from 'gsap';
|
import { gsap } from 'gsap';
|
||||||
import ScrollTrigger from 'gsap/dist/ScrollTrigger';
|
import ScrollTrigger from 'gsap/dist/ScrollTrigger';
|
||||||
import SplitText from 'gsap/dist/SplitText';
|
import SplitText from 'gsap/dist/SplitText';
|
||||||
|
import HomeIlluDev from '$lib/components/HomeIlluDev.svelte';
|
||||||
|
import HomeIlluShapes from '$lib/components/HomeIlluShapes.svelte';
|
||||||
|
|
||||||
let canvasElems: Array<HTMLElement>;
|
let canvasElems: Array<HTMLElement>;
|
||||||
|
let imgElems: Array<HTMLElement>;
|
||||||
let mounted = false;
|
let mounted = false;
|
||||||
|
|
||||||
onMount( () => {
|
onMount( () => {
|
||||||
|
|
||||||
mounted = true;
|
mounted = true;
|
||||||
|
|
@ -16,33 +19,39 @@
|
||||||
gsap.registerPlugin( ScrollTrigger, SplitText );
|
gsap.registerPlugin( ScrollTrigger, SplitText );
|
||||||
|
|
||||||
const sections = document.querySelectorAll('section');
|
const sections = document.querySelectorAll('section');
|
||||||
|
|
||||||
sections.forEach( (section) => {
|
sections.forEach( (section) => {
|
||||||
if ( section.classList.contains('splash')){
|
if ( section.classList.contains('splash')){
|
||||||
let split = new SplitText(section.querySelectorAll('h1'), { type: 'words', wordsClass: 'lineChildren' });
|
let split = new SplitText(section.querySelectorAll('h1'), { type: 'words', wordsClass: 'wordChildren' });
|
||||||
|
split.words.forEach( (word) => {
|
||||||
|
word.innerHTML = word.innerHTML.replace(' ', '');
|
||||||
|
})
|
||||||
gsap.set(split.words, {
|
gsap.set(split.words, {
|
||||||
opacity: 0,
|
opacity: 1,
|
||||||
y: 60,
|
y: -window.innerHeight,
|
||||||
transformOrigin: '50% 100%'
|
transformOrigin: '50% 100%'
|
||||||
})
|
})
|
||||||
gsap.to(split.words, {
|
gsap.to(split.words, {
|
||||||
duration: 0.5,
|
duration: 1,
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
stagger: 0.033,
|
stagger: -0.01,
|
||||||
ease: 'back.out',
|
ease: 'elastic.out(1, .5)',
|
||||||
delay: .3
|
delay: .3
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let split = new SplitText(section.querySelectorAll('h2'), { type: 'lines', linesClass: 'lineChildren' });
|
let split = new SplitText(section.querySelectorAll('h2'), { type: 'words', wordsClass: 'wordChildren' });
|
||||||
gsap.set(split.lines, { transformOrigin: '0% 100%' });
|
split.words.forEach( (word) => {
|
||||||
gsap.set(split.lines, { yPercent: 100, opacity: 0 });
|
word.innerHTML = word.innerHTML.replace(' ', '');
|
||||||
gsap.to(split.lines, { duration: 1, yPercent: 0, opacity: 1, stagger: 0.1, ease: 'power4.out',
|
})
|
||||||
scrollTrigger: { trigger: split.lines, start: 'top 90%', end: 'bottom 70%', scrub: false }
|
gsap.set(split.words, { transformOrigin: '0% 100%' });
|
||||||
|
gsap.set(split.words, { yPercent: 100, opacity: 0 });
|
||||||
|
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('p')) {
|
if (section.querySelector('.toCanvas')) {
|
||||||
let splitp = new SplitText(section.querySelectorAll('p'), { type: 'lines', linesClass: 'lineChildren' });
|
let splitp = new SplitText(section.querySelectorAll('.toCanvas'), { type: 'lines', linesClass: 'lineChildren' });
|
||||||
gsap.set(splitp.lines, { transformOrigin: '0% 100%' });
|
gsap.set(splitp.lines, { transformOrigin: '0% 100%' });
|
||||||
gsap.set(splitp.lines, { yPercent: 100, opacity: 0 });
|
gsap.set(splitp.lines, { yPercent: 100, opacity: 0 });
|
||||||
gsap.to(splitp.lines, { duration: 1, yPercent: 0, opacity: 1, stagger: 0.05, ease: 'power4.out',
|
gsap.to(splitp.lines, { duration: 1, yPercent: 0, opacity: 1, stagger: 0.05, ease: 'power4.out',
|
||||||
|
|
@ -50,9 +59,10 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
canvasElems = Array.from(document.querySelectorAll('.lineChildren'));
|
|
||||||
|
|
||||||
|
})
|
||||||
|
canvasElems = Array.from(document.querySelectorAll('.lineChildren, .wordChildren'));
|
||||||
|
imgElems = Array.from(document.querySelectorAll('img'));
|
||||||
return () => {
|
return () => {
|
||||||
gsap.killTweensOf(canvasElems);
|
gsap.killTweensOf(canvasElems);
|
||||||
ScrollTrigger.getAll().forEach( instance => instance.kill() );
|
ScrollTrigger.getAll().forEach( instance => instance.kill() );
|
||||||
|
|
@ -65,33 +75,49 @@
|
||||||
{/if}
|
{/if}
|
||||||
<article class="scroller">
|
<article class="scroller">
|
||||||
<section class="splash">
|
<section class="splash">
|
||||||
<h1>Simon Flöter creates products that stand out.</h1>
|
<h1>Hallo! I'm Simon.<br> I forge websites<br/><em>that stand out</em> with great beauty.</h1>
|
||||||
</section>
|
</section>
|
||||||
<section class="intro">
|
<section class="intro">
|
||||||
<h2>As a Creative Web Developer ...</h2>
|
<figure class="intro-image">
|
||||||
<p>I specialise in delivering beautifully crafted bespoke websites.</p>
|
<HomeIlluDev />
|
||||||
|
</figure>
|
||||||
|
<h2><em>Creative</em> Development</h2>
|
||||||
|
<p class="toCanvas">I specialise in fashioning exquisitly tailored websites and webapps for the discerning enterprise executive.</p>
|
||||||
<div class="cta">
|
<div class="cta">
|
||||||
<a href="/work" class="button">Learn More</a>
|
<a href="/service" class="button">My Services</a>
|
||||||
<a href="/work" class="button button--primary">Hire Simon</a>
|
<a href="/work" class="button button--primary">Hire Simon</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="more">
|
<section class="design">
|
||||||
<h2>As a UX & Graphic Designer...</h2>
|
<figure class="design-illu">
|
||||||
<p>I have designed Websites, Housestyles, Typefaces, Advertising campaigns and Print publications for them.</p>
|
<HomeIlluShapes />
|
||||||
|
</figure>
|
||||||
|
<h2>Visual Design</h2>
|
||||||
|
<p class="toCanvas">With years in the craft, I've mastered the art of designing websites, user interfaces, illustrations, house styles, and everything betwixt.</p>
|
||||||
<div class="cta">
|
<div class="cta">
|
||||||
<a href="/work" class="button">Learn More</a>
|
<a href="/service" class="button">My Services</a><a href="/work" class="button button--primary">Hire Simon</a>
|
||||||
<a href="/work" class="button button--primary">Hire Simon</a>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="more">
|
<section class="more">
|
||||||
<h2>I create products that help great companies reach their audiences. Need help?</h2>
|
<h2>I create products that help great companies reach their audiences.</h2>
|
||||||
<div class="cta">
|
<div class="cta">
|
||||||
<a href="/work" class="button button--xl">Reach out!</a>
|
<a href="/work" class="button button--xl">Reach out!</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
<HomeCanvas textsToCanvas={canvasElems}/>
|
<HomeCanvas textsToCanvas={canvasElems} imgsToCanvas={imgElems}/>
|
||||||
|
<div class="canvasResizeToThis"></div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
.canvasResizeToThis {
|
||||||
|
position: fixed;
|
||||||
|
top: -10vh;
|
||||||
|
left: -10vw;
|
||||||
|
width: 120vw;
|
||||||
|
height: 120vh;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
.scroller {
|
.scroller {
|
||||||
font-size: clamp(32px, 4.5vw, 4.5vw);
|
font-size: clamp(32px, 4.5vw, 4.5vw);
|
||||||
}
|
}
|
||||||
|
|
@ -99,13 +125,16 @@
|
||||||
scroll-snap-align: start;
|
scroll-snap-align: start;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: var(--spacing-outer);
|
padding: var(--spacing-outer);
|
||||||
overflow: hidden;
|
min-height: 100svh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-outer);
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
padding: var(--spacing-outer) calc(var(--spacing-outer) * 2.5);
|
max-width: 75vw;
|
||||||
}
|
margin: 0 auto;
|
||||||
&:last-child{
|
gap: 0;
|
||||||
padding-bottom: 50svh;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.splash {
|
.splash {
|
||||||
|
|
@ -114,14 +143,37 @@
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
min-height: 100svh;
|
min-height: 100svh;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: var(--spacing-outer);
|
|
||||||
margin-bottom: -1em;
|
margin-bottom: -1em;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: var(--spacing-outer);
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
padding: var(--spacing-outer) calc(var(--spacing-outer) * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.intro-image {
|
||||||
|
position:relative;
|
||||||
|
left: 0;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
margin: 0 0 -.5em 0;
|
||||||
|
z-index: -2;
|
||||||
|
}
|
||||||
|
.design {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.design-illu {
|
||||||
|
position:relative;
|
||||||
|
left: 0;
|
||||||
|
width: 40%;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: -1em;
|
||||||
|
z-index: -2;
|
||||||
}
|
}
|
||||||
h1, h2 {
|
h1, h2 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
letter-spacing: -0.025em;
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal;
|
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
-webkit-touch-callout: none; /* Safari */
|
-webkit-touch-callout: none; /* Safari */
|
||||||
|
|
@ -131,28 +183,44 @@
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
letter-spacing: -0.05em;
|
line-height: 1;
|
||||||
line-height: .9;
|
font-size: 11vw;
|
||||||
font-size: 17vw;
|
|
||||||
margin-top: -.5em;
|
margin-top: -.5em;
|
||||||
// text-align: center;
|
letter-spacing: -0.05em;
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
font-size: 12vw;
|
font-size: 9vw;
|
||||||
|
line-height: .9;
|
||||||
|
}
|
||||||
|
& em {
|
||||||
|
color: var(--color-highlight);
|
||||||
|
font-style: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 1.25em;
|
font-size: 1.5em;
|
||||||
font-weight: 800;
|
letter-spacing: -0.033em;
|
||||||
font-style: italic;
|
margin-bottom: 0;
|
||||||
margin-bottom: .5em;
|
line-height: .9;
|
||||||
|
|
||||||
|
& em {
|
||||||
|
color: var(--color-highlight);
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p {
|
.toCanvas {
|
||||||
font-size: 0.7em;
|
visibility: hidden;
|
||||||
|
font-size: .66em;
|
||||||
|
margin: 1.25em 0 0.25em 0;
|
||||||
-webkit-touch-callout: none; /* Safari */
|
-webkit-touch-callout: none; /* Safari */
|
||||||
-webkit-user-select: none; /* Chrome */
|
-webkit-user-select: none; /* Chrome */
|
||||||
-moz-user-select: none; /* Firefox */
|
-moz-user-select: none; /* Firefox */
|
||||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
font-size: 0.5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
-webkit-touch-callout: none; /* Safari */
|
-webkit-touch-callout: none; /* Safari */
|
||||||
|
|
@ -161,4 +229,15 @@
|
||||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
.cta {
|
||||||
|
margin-top: 0em;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
53
src/routes/about/+page.svelte
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
<script lang='ts'>
|
||||||
|
import * as PIXI from 'pixi.js';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { gsap } from 'gsap';
|
||||||
|
|
||||||
|
onMount( async () => {
|
||||||
|
// const canvas = document.querySelector('canvas') as HTMLCanvasElement;
|
||||||
|
// const app = new PIXI.Application({
|
||||||
|
// backgroundColor: 0x000000,
|
||||||
|
// backgroundAlpha: 0,
|
||||||
|
// resizeTo: window,
|
||||||
|
// antialias: true,
|
||||||
|
// resolution: 2,
|
||||||
|
// view: canvas
|
||||||
|
// })
|
||||||
|
|
||||||
|
// const imageurl = 'work/peak/peak_hero.png'
|
||||||
|
// // create a PIXI texture and create one sprite per quarter of the original image of the texture
|
||||||
|
// const texture = await PIXI.Texture.from(imageurl)
|
||||||
|
// texture.baseTexture.width = window.innerWidth
|
||||||
|
// texture.baseTexture.height = window.innerWidth / 1.5
|
||||||
|
|
||||||
|
// const rows = 50
|
||||||
|
// const cols = 50
|
||||||
|
|
||||||
|
// for (let i = 0; i < rows; i++) {
|
||||||
|
// for (let j = 0; j < cols; j++) {
|
||||||
|
// const thisTexture = new PIXI.Texture(texture.baseTexture, new PIXI.Rectangle(
|
||||||
|
// j * window.innerWidth / cols,
|
||||||
|
// i * window.innerHeight / rows,
|
||||||
|
// window.innerWidth / cols,
|
||||||
|
// window.innerHeight / rows
|
||||||
|
// ))
|
||||||
|
|
||||||
|
// const sprite = new PIXI.Sprite(thisTexture)
|
||||||
|
// sprite.width = window.innerWidth / cols
|
||||||
|
// sprite.height = window.innerHeight / rows
|
||||||
|
// sprite.x = sprite.width * j
|
||||||
|
// sprite.y = sprite.height * i
|
||||||
|
// app.stage.addChild(sprite)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<h1>Hello world</h1>
|
||||||
|
<p>Is this the text you're looking for?</p>
|
||||||
|
</article>
|
||||||
|
<canvas></canvas>
|
||||||
|
|
||||||
|
|
||||||
|
<style src="./about.scss" lang="scss"></style>
|
||||||
10
src/routes/about/about.scss
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
article {
|
||||||
|
padding: var(--spacing-outer);
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
176
src/routes/service/+page.svelte
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import gsap from 'gsap';
|
||||||
|
import ScrollTrigger from 'gsap/dist/ScrollTrigger';
|
||||||
|
import Faq from '$lib/components/Faq.svelte';
|
||||||
|
import ServiceCanvas from './ServiceCanvas.svelte';
|
||||||
|
|
||||||
|
onMount( () => {
|
||||||
|
gsap.registerPlugin( ScrollTrigger );
|
||||||
|
|
||||||
|
let introTl = gsap.timeline({
|
||||||
|
paused: true,
|
||||||
|
});
|
||||||
|
introTl.fromTo('h1', {
|
||||||
|
opacity: 0, yPercent: 200
|
||||||
|
},{
|
||||||
|
opacity: 1, yPercent: 0,
|
||||||
|
duration: .75, ease: 'back.out(.75)'
|
||||||
|
}, 0.1)
|
||||||
|
|
||||||
|
introTl.play();
|
||||||
|
|
||||||
|
gsap.to('.services', {
|
||||||
|
autoAlpha: 1,
|
||||||
|
scrollTrigger: {
|
||||||
|
trigger: 'article',
|
||||||
|
start: 'top top',
|
||||||
|
end: '200px top',
|
||||||
|
scrub: true,
|
||||||
|
// markers: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
ScrollTrigger.getAll().forEach( (trigger) => {
|
||||||
|
trigger.kill();
|
||||||
|
});
|
||||||
|
gsap.killTweensOf('canvas');
|
||||||
|
gsap.killTweensOf('h1');
|
||||||
|
gsap.killTweensOf('section');
|
||||||
|
gsap.killTweensOf('.services');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ServiceCanvas />
|
||||||
|
<article>
|
||||||
|
<h1>What I will (and won't) do to earn a living</h1>
|
||||||
|
<div class="services">
|
||||||
|
<section>
|
||||||
|
<h2>Web Development</h2>
|
||||||
|
<div class="service-content">
|
||||||
|
<ul class="bullets">
|
||||||
|
<li><em>Consultation</em> on the best technology solutions for your situation (eg CMS, frontend frameworks, etc)</li>
|
||||||
|
<li><em>Advice</em> on how to enhance the user experience through savvy use of technology</li>
|
||||||
|
<li><em>Development</em> in HTML/JS/CSS and/or whichever framework is best suited to your project</li>
|
||||||
|
</ul>
|
||||||
|
<div class="tech">
|
||||||
|
<h3>FAQs</h3>
|
||||||
|
<Faq summary="What kind of websites do you create?">
|
||||||
|
<p>In frontend work, I blend professionalism and creativity. My aim is simple: bring your ideas to life. Projects include:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Marketing websites</li>
|
||||||
|
<li>E-commerce websites</li>
|
||||||
|
<li>Mobile web apps</li>
|
||||||
|
<li>Interactive online comics</li>
|
||||||
|
<li>Browser games</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>I center on crafting interfaces that dazzle visually and deliver an instinctive user journey. The essence is to make your users feel at home in the interaction with your content.</p>
|
||||||
|
<p>Should your venture demand a backend touch, like managing databases or Content Management, I'm well-versed in leveraging existing open source solutions. I advocate for savvy fixes, seamlessly tailored to harmonize with your project.</p>
|
||||||
|
</Faq>
|
||||||
|
<Faq summary="What kind of websites do you NOT create?">
|
||||||
|
<p>As a frontend developer, I'm not your guy for the intricate machinery that powers colossal enterprise web applications. Put simply, I can't whip up an Amazon or a TikTok from the ground up.</p>
|
||||||
|
<p>Moreover, my moral code is steadfast. Requests involving, but not confined to, promoting weapons manufacturers or propagating conspiracy theories won't find a home with me. I must politely decline such propositions.</p>
|
||||||
|
</Faq>
|
||||||
|
<Faq summary="Which technologies and frameworks do you use/support?">
|
||||||
|
<p>A web browser grasps just HTML, CSS, and Javascript. Mastery of these is the bedrock for crafting top-notch web applications.</p>
|
||||||
|
<p>Yet, I've treaded diverse coding landscapes, navigating the realms of PHP, Perl, and Python. Among the myriad frameworks danced with, names like React, Svelte, Eleventy, Astro, and the esteemed Ruby on Rails echo.</p>
|
||||||
|
<p>I serve as your counsel, steering you toward the optimal solution tailored to your project's idiosyncrasies.</p>
|
||||||
|
<p>Should you possess a standing website, yearning for expansion, toss me the code, and we'll unravel the possibilities together. Not encountered a site I couldn't tame, so far.</p>
|
||||||
|
<p>And, sometimes, the most fitting scaffold is none at all. I crafted some elegant, straightforward websites in the raw embrace of HTML, CSS, and JS.</p>
|
||||||
|
</Faq>
|
||||||
|
|
||||||
|
<Faq summary="Which Content Management System (CMS) do you recommend?">
|
||||||
|
<p>I've tinkered with various Content Management Systems — the likes of WordPress, Strapi, Builder, Magento, and Shopify. Each carries its own set of virtues and vices.</p>
|
||||||
|
<p>Let's talk about the folks responsible for constructing and upkeeping your content. Only then can we jointly discern the optimal solution.</p>
|
||||||
|
</Faq>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2>UX/Visual Design</h2>
|
||||||
|
<div class="service-content">
|
||||||
|
<ul class="bullets">
|
||||||
|
<li><em>Concept & Mockup</em><br>In a collaborative effort we shall unearth the possibilities your brief holds. Then decide which road to follow down to </li>
|
||||||
|
<li><em>Prototyping</em> for interactive products, to gain understanding of the user experience prior to production</li>
|
||||||
|
<li><em>Illustration & animation</em> to bring your ideas to life</li>
|
||||||
|
<li><em>Data visualisation</em> to aid crucial information cross the seas of abstraction</li>
|
||||||
|
</ul>
|
||||||
|
<div class="tech">
|
||||||
|
<h3>FAQs</h3>
|
||||||
|
<Faq summary="What do you design?">
|
||||||
|
<p>Primarily, I craft beautiful web experiences for my clients, aiming to seize their audience's imagination.</p>
|
||||||
|
<p>I first was schooled in the art of graphic design. Over time, my focus shifted towards web projects, pulling me into the worlds of development and more UX/interaction-centric design.</p>
|
||||||
|
<p>Beyond websites and user interfaces, I've crafted promotional posters and publications for print, as well as entire Housestyles for budding brands.</p>
|
||||||
|
<p>And, well, I'm also an Illustrator, but that's a tale of its own. You can follow it <a href="https://instagram.com/floter.ink">on instagram</a>.</p>
|
||||||
|
</Faq>
|
||||||
|
<Faq summary="What do you NOT design?">
|
||||||
|
<p>Despite doing animations for websites, mostly achieved through code, I am not a traditional motion designer. If you require a static video file as final product, you will want to look for someone with skills in video editing and motion design software such as After Effects.</p>
|
||||||
|
<p>However it is easy to add animations made through such a process to a website and integrate them with the rest of the content.</p>
|
||||||
|
</Faq>
|
||||||
|
<Faq summary="What do you require to start designing?">
|
||||||
|
<p>A good brief includes all limitations and aspirations of your project, your businesses proposition, values and intentions as well as any information you have on your target audience. References to competitors and examples of similar products you like are very helpful as well. Generally though, it all starts with a chat between you and yours truly.</p>
|
||||||
|
</Faq>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
article {
|
||||||
|
margin: auto;
|
||||||
|
max-width: 1200px;
|
||||||
|
padding: calc(50vh - var(--spacing-outer) - 35vw) var(--spacing-outer) var(--spacing-outer) var(--spacing-outer);
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
padding: calc(50vh - var(--spacing-outer) - 12vw) var(--spacing-outer) var(--spacing-outer) var(--spacing-outer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
|
||||||
|
font-size: 14vw;
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
font-size: 8vw;
|
||||||
|
letter-spacing: -0.045em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.services {
|
||||||
|
opacity: 0; //changed in ServiceCanvas
|
||||||
|
}
|
||||||
|
.service-content {
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
display: flex;
|
||||||
|
gap: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.service-content > :first-child {
|
||||||
|
flex: 0 0 40%;
|
||||||
|
}
|
||||||
|
.service-content > *,
|
||||||
|
.service-content > * > :first-child{
|
||||||
|
margin-top: 0;
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
padding-bottom: .5em;
|
||||||
|
}
|
||||||
|
em {
|
||||||
|
font-weight: 800;
|
||||||
|
color: var(--color-highlight);
|
||||||
|
}
|
||||||
|
ul li {
|
||||||
|
margin-bottom: .75em;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
li, p {
|
||||||
|
font-size: 1.15em;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
189
src/routes/service/ServiceCanvas.svelte
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import * as PIXI from 'pixi.js';
|
||||||
|
import { BulgePinchFilter } from 'pixi-filters';
|
||||||
|
import gsap from 'gsap';
|
||||||
|
import ScrollTrigger from 'gsap/dist/ScrollTrigger';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
let canvas: HTMLCanvasElement;
|
||||||
|
let introDone = false;
|
||||||
|
|
||||||
|
onMount( () => {
|
||||||
|
|
||||||
|
let is_fine = window.matchMedia('(pointer:fine)').matches
|
||||||
|
let is_landscape = window.matchMedia('(orientation:landscape)').matches
|
||||||
|
|
||||||
|
gsap.registerPlugin(ScrollTrigger);
|
||||||
|
|
||||||
|
let app = new PIXI.Application({
|
||||||
|
resizeTo: window,
|
||||||
|
antialias: true,
|
||||||
|
autoDensity: true,
|
||||||
|
resolution: 2,
|
||||||
|
backgroundColor: 'rgb(255, 255, 255)',
|
||||||
|
backgroundAlpha: 0,
|
||||||
|
view: canvas,
|
||||||
|
});
|
||||||
|
|
||||||
|
let textgroup = new PIXI.Container();
|
||||||
|
textgroup.pivot.set(0, 0);
|
||||||
|
textgroup.x = 0;
|
||||||
|
textgroup.y = - window.innerHeight;
|
||||||
|
textgroup.height = window.innerHeight;
|
||||||
|
textgroup.width = window.innerWidth;
|
||||||
|
app.stage.addChild(textgroup);
|
||||||
|
|
||||||
|
let tweens: Array<GSAPTween> = [];
|
||||||
|
|
||||||
|
let fontSize = window.innerHeight / 3;
|
||||||
|
|
||||||
|
function createText(string: string){
|
||||||
|
let text = new PIXI.Text(string,
|
||||||
|
{ fontFamily: 'Stratos',
|
||||||
|
fontSize: fontSize,
|
||||||
|
// fontWeight: '800',
|
||||||
|
lineHeight: 0,
|
||||||
|
letterSpacing: -20,
|
||||||
|
fill: `#000`,
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
text.anchor.set(0);
|
||||||
|
textgroup.addChild(text);
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
let allTexts = [
|
||||||
|
createText('SERVICES SERVICES '), createText('SERVICES SERVICES '),
|
||||||
|
createText('CONSULTATION DESIGN WEB DEVELOPMENT '), createText('CONSULTATION DESIGN WEB DEVELOPMENT '),
|
||||||
|
createText('SERVICES SERVICES '), createText('SERVICES SERVICES '),
|
||||||
|
createText('CONSULTATION DESIGN WEB DEVELOPMENT '), createText('CONSULTATION DESIGN WEB DEVELOPMENT ')
|
||||||
|
]
|
||||||
|
|
||||||
|
let textRows = [
|
||||||
|
[allTexts[0], allTexts[1]],
|
||||||
|
[allTexts[2], allTexts[3]],
|
||||||
|
[allTexts[4], allTexts[5]],
|
||||||
|
[allTexts[6], allTexts[7]]
|
||||||
|
]
|
||||||
|
textRows.forEach( (row, index) => {
|
||||||
|
if (index % 2 === 0) {
|
||||||
|
row[0].x = 0;
|
||||||
|
row[1].x = row[0].width;
|
||||||
|
} else {
|
||||||
|
row[0].x = -row[0].width;
|
||||||
|
row[1].x = 0;
|
||||||
|
}
|
||||||
|
row[0].y = (fontSize * 0.8 * index);
|
||||||
|
row[1].y = (fontSize * 0.8 * index);
|
||||||
|
})
|
||||||
|
|
||||||
|
let textRowsright = gsap.to([textRows[0], textRows[2]], {
|
||||||
|
x: '+=' + -textRows[0][0].width,
|
||||||
|
duration: 10,
|
||||||
|
ease: 'none',
|
||||||
|
repeat: -1,
|
||||||
|
overwrite: true
|
||||||
|
})
|
||||||
|
tweens.push(textRowsright);
|
||||||
|
|
||||||
|
let textRowsLeft = gsap.to([textRows[1], textRows[3]], {
|
||||||
|
x: '+=' + textRows[1][0].width,
|
||||||
|
duration: 10,
|
||||||
|
ease: 'none',
|
||||||
|
repeat: -1,
|
||||||
|
overwrite: true
|
||||||
|
})
|
||||||
|
tweens.push(textRowsLeft);
|
||||||
|
|
||||||
|
//move textgroup so left side is offscreen
|
||||||
|
textgroup.x = -textRows[0][0].width/4;
|
||||||
|
textgroup.rotation = -0.2;
|
||||||
|
textgroup.alpha = 0;
|
||||||
|
|
||||||
|
let bulgefilter = new BulgePinchFilter();
|
||||||
|
bulgefilter.radius = is_landscape ? window.innerWidth / 2 : window.innerWidth;
|
||||||
|
bulgefilter.strength = .66;
|
||||||
|
bulgefilter.center = new PIXI.Point(0.5, 0.5);
|
||||||
|
app.stage.filters = [bulgefilter];
|
||||||
|
|
||||||
|
let textgroupIn = gsap.to(textgroup, {
|
||||||
|
y: is_landscape ? textRows[0][0].height * 0.4 : textRows[0][0].height * 0.15,
|
||||||
|
alpha: 1,
|
||||||
|
duration: 1.5,
|
||||||
|
ease: 'power4.out',
|
||||||
|
overwrite: true,
|
||||||
|
onComplete: () => {
|
||||||
|
introDone = true;
|
||||||
|
createScrollTrigger();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
tweens.push(textgroupIn);
|
||||||
|
|
||||||
|
let mouse = { x: 0.5, y: 0.5 };
|
||||||
|
window.addEventListener('mousemove', (e) => {
|
||||||
|
gsap.to(mouse, {
|
||||||
|
x: e.clientX / window.innerWidth,
|
||||||
|
duration: 1,
|
||||||
|
ease: 'power3.out',
|
||||||
|
overwrite: true
|
||||||
|
})
|
||||||
|
mouse.y = e.clientY / window.innerHeight;
|
||||||
|
})
|
||||||
|
|
||||||
|
let elapsed = 0;
|
||||||
|
app.ticker.add((delta) => {
|
||||||
|
elapsed += delta;
|
||||||
|
bulgefilter.center = new PIXI.Point(mouse.x, 0.5);
|
||||||
|
})
|
||||||
|
|
||||||
|
function createScrollTrigger() {
|
||||||
|
gsap.to([textRows[0], textRows[1]], {
|
||||||
|
y: '+=' + -textRows[0][0].height * 0.9,
|
||||||
|
duration: 1,
|
||||||
|
ease: 'none',
|
||||||
|
scrollTrigger: {
|
||||||
|
trigger: 'article',
|
||||||
|
start: 'top top',
|
||||||
|
end: '200px top',
|
||||||
|
scrub: true,
|
||||||
|
// markers: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
gsap.to([textRows[2], textRows[3]], {
|
||||||
|
y: '+=' + textRows[0][0].height * 0.9,
|
||||||
|
duration: 1,
|
||||||
|
ease: 'none',
|
||||||
|
scrollTrigger: {
|
||||||
|
trigger: 'article',
|
||||||
|
start: 'top top',
|
||||||
|
end: '200px top',
|
||||||
|
scrub: true,
|
||||||
|
// markers: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
app.destroy(true, { children: true, texture: true, baseTexture: true });
|
||||||
|
tweens.forEach( tween => tween.kill() );
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<canvas bind:this={canvas} id="service-canvas"></canvas>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#service-canvas {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
/* z-index: 2; */
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import WorkCanvas from '$lib/components/WorkCanvas.svelte';
|
import WorkCanvas from '$lib/components/WorkCanvas.svelte';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { workClickHandler, initWorkPage } from './workUtils.js';
|
import { workClickHandler, initWorkPage } from './workUtils.js';
|
||||||
import { workbulge } from '$lib/utils/stores.js';
|
import { workbulge } from '$lib/utils/stores.js';
|
||||||
import { CldImage } from 'svelte-cloudinary';
|
import { CldImage } from 'svelte-cloudinary';
|
||||||
import { browser } from '$app/environment';
|
|
||||||
import { fade } from 'svelte/transition';
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
|
const orderedPosts = data.posts.sort((a, b) => {
|
||||||
|
return a.meta.order - b.meta.order;
|
||||||
|
});
|
||||||
|
|
||||||
let canvasTextElems: Array<HTMLElement>;
|
let canvasTextElems: Array<HTMLElement>;
|
||||||
let canvasImgElems: Array<HTMLElement>;
|
let canvasImgElems: Array<HTMLElement>;
|
||||||
let bulge = {factor: 0};
|
let bulge = {factor: 0};
|
||||||
|
|
@ -18,40 +20,52 @@
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const headline: HTMLElement = document.querySelector('.headline') as HTMLElement;
|
const headline: HTMLElement = document.querySelector('.headline') as HTMLElement;
|
||||||
|
const headlines: Array<HTMLElement> = Array.from(document.querySelectorAll('h2, li'));
|
||||||
const images: Array<HTMLElement> = Array.from(document.querySelectorAll('.work img'));
|
const images: Array<HTMLElement> = Array.from(document.querySelectorAll('.work img'));
|
||||||
let canvasElems = initWorkPage( headline, images );
|
let canvasElems = initWorkPage( headlines, images );
|
||||||
canvasTextElems = canvasElems.text as Array<HTMLElement>;
|
canvasTextElems = canvasElems.text as Array<HTMLElement>;
|
||||||
canvasImgElems = canvasElems.images;
|
canvasImgElems = canvasElems.images;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<div class="works-wrapper">
|
||||||
|
|
||||||
<h1 class="headline"><span>Happy Clients</span></h1>
|
<h1 class="headline"><span>Outstanding work</span></h1>
|
||||||
<div class="works">
|
<div class="works">
|
||||||
|
|
||||||
{#each data.posts as work, i}
|
{#each orderedPosts as work, i}
|
||||||
<a
|
<a
|
||||||
data-sveltekit-preload-data
|
data-sveltekit-preload-data
|
||||||
href="{work.path}"
|
href="{work.path}"
|
||||||
class="work"
|
class="work"
|
||||||
on:click={ (e) => workClickHandler(e) }
|
on:click={ (e) => workClickHandler(e) }
|
||||||
>
|
>
|
||||||
<CldImage
|
<CldImage
|
||||||
src={work.meta.header_bg_image}
|
src={work.meta.header_bg_image}
|
||||||
sizes="(min-width: 768px) 20vw, 50vw"
|
sizes={ i === 0 ? `(min-width: 768px) 60vw, 50vw` : `(min-width: 768px) 20vw, 50vw`}
|
||||||
alt={work.meta.title}
|
alt={work.meta.title}
|
||||||
width="2100"
|
width="2100"
|
||||||
height="1400"
|
height="1400"
|
||||||
objectFit="fill"
|
objectFit="fill"
|
||||||
loading= {i < 10 ? "eager" : "lazy"}
|
loading= "lazy"
|
||||||
/>
|
/>
|
||||||
<h2>{work.meta.title}</h2>
|
<div class="work-info">
|
||||||
</a>
|
<h2 class="title"><span class="title-words">{work.meta.title}</span></h2>
|
||||||
{/each}
|
{#if work.meta.tags}
|
||||||
</div>
|
<ul class="tags">
|
||||||
<WorkCanvas
|
{#each work.meta.tags as tag, index}
|
||||||
textsToCanvas={canvasTextElems}
|
<li class="tag">{tag}{index < work.meta.tags.length-1 ? ' | ' : ''}</li>
|
||||||
imgsToCanvas={canvasImgElems}
|
{/each}
|
||||||
bulgeFactor={bulge.factor}
|
</ul>
|
||||||
/>
|
{/if}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<WorkCanvas
|
||||||
|
textsToCanvas={canvasTextElems}
|
||||||
|
imgsToCanvas={canvasImgElems}
|
||||||
|
bulgeFactor={bulge.factor}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style src="./work.scss" lang="scss"></style>
|
<style src="./work.scss" lang="scss"></style>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
export async function load( { params }: { params: { slug: string }} ){
|
export async function load( { params }: { params: { slug: string }} ){
|
||||||
try {
|
try {
|
||||||
const post = await import(`../md/${params.slug}.md`)
|
const post = await import(`../md/${params.slug}.md`)
|
||||||
const { title, date, header_bg_image, svg, video } = post.metadata
|
const { title, date, header_bg_image, svg, video, tags } = post.metadata
|
||||||
const Content = post.default.render()
|
const Content = post.default.render()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -10,6 +10,7 @@ export async function load( { params }: { params: { slug: string }} ){
|
||||||
header_bg_image,
|
header_bg_image,
|
||||||
svg,
|
svg,
|
||||||
video,
|
video,
|
||||||
|
tags,
|
||||||
Content,
|
Content,
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
gsap.to('.work', {
|
gsap.to('.work', {
|
||||||
xPercent: -100,
|
xPercent: -100,
|
||||||
duration: .4,
|
duration: .6,
|
||||||
ease: "expo.out",
|
ease: "expo.out",
|
||||||
delay: .2
|
delay: .2
|
||||||
})
|
})
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
|
|
||||||
gsap.to('.heromask', {
|
gsap.to('.heromask', {
|
||||||
clipPath: "polygon(0 0, 60% 0, 35% 100%, 0% 100%)",
|
clipPath: "polygon(0 0, 60% 0, 35% 100%, 0% 100%)",
|
||||||
duration: .6,
|
duration: 1,
|
||||||
ease: "cubic.inOut",
|
ease: "power4.out",
|
||||||
onStart: () => {
|
onStart: () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.querySelector('.coverclone')?.remove();
|
document.querySelector('.coverclone')?.remove();
|
||||||
|
|
@ -35,12 +35,12 @@
|
||||||
},
|
},
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
gsap.to('.heromask', {
|
gsap.to('.heromask', {
|
||||||
ease: "power1.inOut",
|
ease: "none",
|
||||||
clipPath: "polygon(0 0, 50% 0, 50% 100%, 0% 100%)",
|
clipPath: "polygon(0 0, 50% 0, 50% 100%, 0% 100%)",
|
||||||
scrollTrigger: {
|
scrollTrigger: {
|
||||||
trigger: '.work',
|
trigger: '.work',
|
||||||
start: '0% top',
|
start: 'top top',
|
||||||
end: `100px top`,
|
end: `200px top`,
|
||||||
scrub: true
|
scrub: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -138,6 +138,13 @@
|
||||||
<article class="work">
|
<article class="work">
|
||||||
{#if visible}
|
{#if visible}
|
||||||
<div class="work-content">
|
<div class="work-content">
|
||||||
|
{#if data.tags != undefined && data.tags.length > 0 }
|
||||||
|
<div class="tags">
|
||||||
|
{#each data.tags as tag }
|
||||||
|
<div class="tag">{tag}</div>
|
||||||
|
{ /each }
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<h1><span class="svg-logo">{@html data.svg}</span><span class="name">{data.title}</span></h1>
|
<h1><span class="svg-logo">{@html data.svg}</span><span class="name">{data.title}</span></h1>
|
||||||
<div class="work-content-text">
|
<div class="work-content-text">
|
||||||
{@html data.Content.html}
|
{@html data.Content.html}
|
||||||
|
|
@ -152,8 +159,8 @@
|
||||||
min-height: 100svh;
|
min-height: 100svh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
// background-color: var(--color-bg);
|
|
||||||
transform: translateY(100%);
|
transform: translateY(100%);
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
}
|
}
|
||||||
|
|
@ -167,6 +174,7 @@
|
||||||
|
|
||||||
& a {
|
& a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
color: var(--color-highlight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.heromask {
|
.heromask {
|
||||||
|
|
@ -196,10 +204,9 @@
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
|
|
||||||
& :last-child {
|
& > :last-child {
|
||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
margin-left: 40vw;
|
margin-left: 40vw;
|
||||||
max-width: 60vw;
|
max-width: 60vw;
|
||||||
|
|
@ -208,19 +215,14 @@
|
||||||
padding-right: calc(var(--spacing-outer) * 2.5);
|
padding-right: calc(var(--spacing-outer) * 2.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.work-content-text {
|
|
||||||
@media screen and (min-width: 768px) {
|
|
||||||
border-top: 1px solid var(--color-text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h1 {
|
h1 {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
padding: 0 0 1em 0;
|
padding: 0 0 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
& .name {
|
& .name {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
@ -237,6 +239,37 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.tags {
|
||||||
|
padding-bottom: .25em;
|
||||||
|
font-size: 1em;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
line-height: 1.1;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: calc(100% + var(--spacing-outer) * 2.5);
|
||||||
|
height: 1px;
|
||||||
|
background-color: var(--color-text);
|
||||||
|
margin-top: .5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tag {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: .5em;
|
||||||
|
padding: .125em 0;
|
||||||
|
font-weight: 400;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: -.005em;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: ','
|
||||||
|
}
|
||||||
|
&:last-child:after {
|
||||||
|
content: none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:global(.header-nav){
|
:global(.header-nav){
|
||||||
transition: all .3s cubic-bezier(0.075, 0.82, 0.165, 1);
|
transition: all .3s cubic-bezier(0.075, 0.82, 0.165, 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,12 @@
|
||||||
title: Adidas
|
title: Adidas
|
||||||
header_bg_image: adidas_hero_ceurd8
|
header_bg_image: adidas_hero_ceurd8
|
||||||
order: 12
|
order: 12
|
||||||
|
tags: ['graphic design', 'illustration']
|
||||||
description: Adidas, as you might have heard, is an international sports and lifestyle clothing brand. I worked on several digital campaigns as a graphic designer and illustrator.
|
description: Adidas, as you might have heard, is an international sports and lifestyle clothing brand. I worked on several digital campaigns as a graphic designer and illustrator.
|
||||||
svg: '<svg id="adidas-logo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 1000 674.2" style="enable-background:new 0 0 1000 674.2; fill: currentColor" xml:space="preserve"><path d="M654.5 442.2 448.9 84.8 596.6 0l255.7 442.2H654.5"/><path d="m106.8 392.1 147.7-85.4 78.2 135.5H135.5l-28.7-50.1"/><path d="M396.7 670.2h42V500.1h-42v170.1z"/><path d="M923.6 674.2c-47 0-75.3-24.3-76.8-58.5h44.3c0 10.7 6.7 26.4 35.4 26.9 19.1 0 28.1-11.3 28.1-19.7-1.1-13.4-18-14.5-35.9-17.4-18-2.9-33.3-6.1-44.3-11.8-14.1-7.3-23.7-22.9-23.7-40.9 0-30.4 26.4-54.5 70.3-54.5 42.6 0 69.6 22.4 72.4 55.6h-42.8c-.4-9-2.1-23.1-27.3-23.1-17 0-28.3 3.4-29.2 15.3 0 17.4 35.4 16.2 62.9 23.5 26.4 6.7 43.2 23.1 43.2 46.1-.2 42.2-34.4 58.5-76.6 58.5"/><path d="m280 240.4 147.7-85.2 165.7 287H438.8v42h-42V442L280 240.4"/><path class="st0" d="M283.8 674.2c-48.9 0-88.7-39.9-88.7-88.3 0-48.9 39.7-87.5 88.7-87.5 18.5 0 35.4 5 50.1 15.1v-71.3h42v228h-42v-11.3c-14.8 9.6-31.6 15.3-50.1 15.3zm-48.4-88.3c0 26.4 22.5 48.3 49.5 48.3 26.4 0 48.9-22 48.9-48.3 0-26.4-22.5-48.9-48.9-48.9-26.9 0-49.5 22.5-49.5 48.9"/><path class="st0" d="M594.5 442.2H636v228h-41.5v-11.3c-14.1 9.6-31.5 15.3-50.6 15.3-48.3 0-88.1-39.9-88.1-88.3 0-48.9 39.7-87.5 88.1-87.5 19.1 0 35.9 5 50.6 15.1v-71.3zm-97.8 143.7c0 26.4 22.5 48.3 48.3 48.3 26.9 0 49.5-22 49.5-48.3 0-26.4-22.5-48.9-49.5-48.9-25.8 0-48.3 22.5-48.3 48.9"/><path class="st0" d="M738.2 674.2c-48.2 0-88.1-39.9-88.1-88.3 0-48.9 39.9-87.5 88.1-87.5 18.5 0 35.9 5 50.1 15.1v-13.6h42v170.3h-42v-11.3c-14.2 9.6-31 15.3-50.1 15.3zM691 585.9c0 26.4 22.5 48.3 48.9 48.3s48.3-22 48.3-48.3c0-26.4-22-48.9-48.3-48.9-26.4 0-48.9 22.5-48.9 48.9"/><path class="st0" d="M40.5 585.9c0 26.4 22.5 48.3 48.9 48.3 26.9 0 49.5-22 49.5-48.3 0-26.4-22.5-48.9-49.5-48.9-26.3 0-48.9 22.5-48.9 48.9zm47.8 88.3c-48.4 0-88.3-40-88.3-88.3 0-48.9 39.9-87.5 88.3-87.5 18.5 0 35.9 5 50.6 15.1v-13.6h41.5v170.3h-41.5v-11.3c-14.1 9.6-31.5 15.3-50.6 15.3"/></svg>'
|
svg: '<svg id="adidas-logo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 1000 674.2" style="enable-background:new 0 0 1000 674.2; fill: currentColor" xml:space="preserve"><path d="M654.5 442.2 448.9 84.8 596.6 0l255.7 442.2H654.5"/><path d="m106.8 392.1 147.7-85.4 78.2 135.5H135.5l-28.7-50.1"/><path d="M396.7 670.2h42V500.1h-42v170.1z"/><path d="M923.6 674.2c-47 0-75.3-24.3-76.8-58.5h44.3c0 10.7 6.7 26.4 35.4 26.9 19.1 0 28.1-11.3 28.1-19.7-1.1-13.4-18-14.5-35.9-17.4-18-2.9-33.3-6.1-44.3-11.8-14.1-7.3-23.7-22.9-23.7-40.9 0-30.4 26.4-54.5 70.3-54.5 42.6 0 69.6 22.4 72.4 55.6h-42.8c-.4-9-2.1-23.1-27.3-23.1-17 0-28.3 3.4-29.2 15.3 0 17.4 35.4 16.2 62.9 23.5 26.4 6.7 43.2 23.1 43.2 46.1-.2 42.2-34.4 58.5-76.6 58.5"/><path d="m280 240.4 147.7-85.2 165.7 287H438.8v42h-42V442L280 240.4"/><path class="st0" d="M283.8 674.2c-48.9 0-88.7-39.9-88.7-88.3 0-48.9 39.7-87.5 88.7-87.5 18.5 0 35.4 5 50.1 15.1v-71.3h42v228h-42v-11.3c-14.8 9.6-31.6 15.3-50.1 15.3zm-48.4-88.3c0 26.4 22.5 48.3 49.5 48.3 26.4 0 48.9-22 48.9-48.3 0-26.4-22.5-48.9-48.9-48.9-26.9 0-49.5 22.5-49.5 48.9"/><path class="st0" d="M594.5 442.2H636v228h-41.5v-11.3c-14.1 9.6-31.5 15.3-50.6 15.3-48.3 0-88.1-39.9-88.1-88.3 0-48.9 39.7-87.5 88.1-87.5 19.1 0 35.9 5 50.6 15.1v-71.3zm-97.8 143.7c0 26.4 22.5 48.3 48.3 48.3 26.9 0 49.5-22 49.5-48.3 0-26.4-22.5-48.9-49.5-48.9-25.8 0-48.3 22.5-48.3 48.9"/><path class="st0" d="M738.2 674.2c-48.2 0-88.1-39.9-88.1-88.3 0-48.9 39.9-87.5 88.1-87.5 18.5 0 35.9 5 50.1 15.1v-13.6h42v170.3h-42v-11.3c-14.2 9.6-31 15.3-50.1 15.3zM691 585.9c0 26.4 22.5 48.3 48.9 48.3s48.3-22 48.3-48.3c0-26.4-22-48.9-48.3-48.9-26.4 0-48.9 22.5-48.9 48.9"/><path class="st0" d="M40.5 585.9c0 26.4 22.5 48.3 48.9 48.3 26.9 0 49.5-22 49.5-48.3 0-26.4-22.5-48.9-49.5-48.9-26.3 0-48.9 22.5-48.9 48.9zm47.8 88.3c-48.4 0-88.3-40-88.3-88.3 0-48.9 39.9-87.5 88.3-87.5 18.5 0 35.9 5 50.6 15.1v-13.6h41.5v170.3h-41.5v-11.3c-14.1 9.6-31.5 15.3-50.6 15.3"/></svg>'
|
||||||
---
|
---
|
||||||
|
|
||||||
|
# adidas is all in
|
||||||
|
|
||||||
Adidas, as you might have heard, is an international sports and lifestyle clothing brand. I worked on several digital campaigns as a graphic designer and illustrator.
|
Adidas, as you might have heard, is an international sports and lifestyle clothing brand. I worked on several digital campaigns as a graphic designer and illustrator.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ title: Formo.bio
|
||||||
header_bg_image: formo_hero_xgb6xo
|
header_bg_image: formo_hero_xgb6xo
|
||||||
video: /work/formo/formo-rec.webm
|
video: /work/formo/formo-rec.webm
|
||||||
order: 12
|
order: 12
|
||||||
|
tags: ['tech consultancy', 'web development', 'UX Design']
|
||||||
description: Formo, as you might have heard, is an international sports and lifestyle clothing brand. I worked on several digital campaigns as a graphic designer and illustrator.
|
description: Formo, as you might have heard, is an international sports and lifestyle clothing brand. I worked on several digital campaigns as a graphic designer and illustrator.
|
||||||
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70 20" style="enable-background:new 0 0 70 20" xml:space="preserve"><path d="m3.4 5.6 7.9-3.3c.1 0 .1-.1.1-.2l-.9-2c-.1-.1-.2-.1-.2-.1L2.4 3.3C.9 3.9 0 5.3 0 6.9v12.3c0 .1.1.1.1.1h2.2c.1 0 .1-.1.1-.1v-8.7c.2.1.3.1.5.2l7.2 1.8c.1 0 .1 0 .1-.1l.6-2.1c0-.1 0-.1-.1-.1L3.6 8.3C2.7 8 2.5 7.2 2.5 7s0-1 .9-1.4zm59.7.7c-3.8 0-6.9 3-6.9 6.8s3.1 6.8 6.9 6.8 6.9-3 6.9-6.8-3.1-6.8-6.9-6.8zm0 11.1c-2.4 0-4.4-1.9-4.4-4.3s2-4.3 4.4-4.3 4.4 1.9 4.4 4.3-2 4.3-4.4 4.3zM18.8 6.3c-3.8 0-6.9 3-6.9 6.8s3.1 6.8 6.9 6.8 6.9-3 6.9-6.8-3.1-6.8-6.9-6.8zm0 11.1c-2.4 0-4.4-1.9-4.4-4.3s2-4.3 4.4-4.3 4.4 1.9 4.4 4.3-2 4.3-4.4 4.3zM53.1 7.1c-.9-.7-2-.9-3-.6l-3.2.9c-.3.1-.6.2-.9.4-.2-.3-.4-.5-.7-.7-.9-.7-2-.9-3-.6l-3.3.9c-1.6.4-2.7 1.9-2.7 3.5v8.3c0 .1.1.1.1.1h2.2c.1 0 .1-.1.1-.1v-8.3c0-.5.4-1 .9-1.1l3.2-.9c.4-.1.7.1.8.2.3.2.4.5.4.8v9.4c0 .1.1.1.1.1h2.2c.1 0 .1-.1.1-.1V11c0-.5.4-1 .9-1.1l3.2-.9c.4-.1.7.1.8.2.3.2.4.5.4.8v9.4c0 .1.1.1.1.1H54c.1 0 .1 0 .1-.1V9.9c.4-1.1-.1-2.1-1-2.8zm-23 .3c-1.6.4-2.7 1.9-2.7 3.5v8.3c0 .1.1.1.1.1h2.2c.1 0 .1-.1.1-.1v-8.3c0-.5.4-1 .9-1.1l4.6-1.3c.1 0 .1-.1.1-.1l-.6-2.1c0-.1-.1-.1-.1-.1l-4.6 1.2z" style="fill:currentColor"/></svg>'
|
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70 20" style="enable-background:new 0 0 70 20" xml:space="preserve"><path d="m3.4 5.6 7.9-3.3c.1 0 .1-.1.1-.2l-.9-2c-.1-.1-.2-.1-.2-.1L2.4 3.3C.9 3.9 0 5.3 0 6.9v12.3c0 .1.1.1.1.1h2.2c.1 0 .1-.1.1-.1v-8.7c.2.1.3.1.5.2l7.2 1.8c.1 0 .1 0 .1-.1l.6-2.1c0-.1 0-.1-.1-.1L3.6 8.3C2.7 8 2.5 7.2 2.5 7s0-1 .9-1.4zm59.7.7c-3.8 0-6.9 3-6.9 6.8s3.1 6.8 6.9 6.8 6.9-3 6.9-6.8-3.1-6.8-6.9-6.8zm0 11.1c-2.4 0-4.4-1.9-4.4-4.3s2-4.3 4.4-4.3 4.4 1.9 4.4 4.3-2 4.3-4.4 4.3zM18.8 6.3c-3.8 0-6.9 3-6.9 6.8s3.1 6.8 6.9 6.8 6.9-3 6.9-6.8-3.1-6.8-6.9-6.8zm0 11.1c-2.4 0-4.4-1.9-4.4-4.3s2-4.3 4.4-4.3 4.4 1.9 4.4 4.3-2 4.3-4.4 4.3zM53.1 7.1c-.9-.7-2-.9-3-.6l-3.2.9c-.3.1-.6.2-.9.4-.2-.3-.4-.5-.7-.7-.9-.7-2-.9-3-.6l-3.3.9c-1.6.4-2.7 1.9-2.7 3.5v8.3c0 .1.1.1.1.1h2.2c.1 0 .1-.1.1-.1v-8.3c0-.5.4-1 .9-1.1l3.2-.9c.4-.1.7.1.8.2.3.2.4.5.4.8v9.4c0 .1.1.1.1.1h2.2c.1 0 .1-.1.1-.1V11c0-.5.4-1 .9-1.1l3.2-.9c.4-.1.7.1.8.2.3.2.4.5.4.8v9.4c0 .1.1.1.1.1H54c.1 0 .1 0 .1-.1V9.9c.4-1.1-.1-2.1-1-2.8zm-23 .3c-1.6.4-2.7 1.9-2.7 3.5v8.3c0 .1.1.1.1.1h2.2c.1 0 .1-.1.1-.1v-8.3c0-.5.4-1 .9-1.1l4.6-1.3c.1 0 .1-.1.1-.1l-.6-2.1c0-.1-.1-.1-.1-.1l-4.6 1.2z" style="fill:currentColor"/></svg>'
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ title: JustPeace Labs
|
||||||
header_bg_image: jpl_hero_eukxaw
|
header_bg_image: jpl_hero_eukxaw
|
||||||
description: JustPeace Labs is a non-profit organization that works with local communities to build peace and prevent violence.
|
description: JustPeace Labs is a non-profit organization that works with local communities to build peace and prevent violence.
|
||||||
order: 11
|
order: 11
|
||||||
|
tags: ['branding', 'logo design', 'graphic design', 'illustration']
|
||||||
svg: '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Layer_1" x="0" y="0" viewBox="0 0 240 63" style="enable-background:new 0 0 240 63" xml:space="preserve"><style>.st0{fill:currentColor}.st1{fill:currentColor}</style><g id="Layer_1-2"><path class="st0" d="M82.4 23.4c.4-2.3.6-4.7.5-7.1V3.1h4.6v13.1c.1 2.5 0 5-.3 7.5-.8 4.1-4.9 6-7.4 6.1l-1.1-2.4c1.9-.6 3.3-2.1 3.7-4zM92 3.1h4.5v12.3c0 5.1 1.6 6.2 4.4 6.2s4.3-1.3 4.3-6.2V3.1h4.5v12.7c0 6.1-3 9.5-8.9 9.5-6.6 0-8.8-3.8-8.8-9.6V3.1zM114 20.3c1.7.9 3.7 1.4 5.7 1.4 2.4 0 3.2-.8 3.2-2.2s-.9-2.2-4.2-3.9c-2.6-1.3-5.4-3.2-5.4-6.8 0-4.3 3.5-5.9 7.7-5.9 2-.1 3.9.4 5.7 1.3l-.8 3.6c-1.4-.9-3.1-1.4-4.7-1.4-2.4 0-3.3.9-3.3 2.2 0 1.6 1.1 2.2 3.8 3.7 3.4 1.8 6 3.4 6 7 0 4-3.1 6.1-7.5 6.1-2.3 0-4.5-.4-6.6-1.3l.4-3.8zM135.3 6.6H129V3.1h17.2v3.5h-6.3V25h-4.6V6.6zM149.4 3.1h1.4c2.4 0 4.4-.2 6.5-.2 5 0 8 2.2 8 7.6 0 5-3.1 8-8.8 8H154V25h-4.6V3.1zm7 11.8c2.2 0 4.3-.9 4.3-4.6 0-2.8-1.5-4.3-4.4-4.2-.8 0-1.6.1-2.4.2v8.4c.8.2 1.6.2 2.5.2zM168.4 3.1h13.4v3.5H173V12h6.8v3.5H173v5.9h9.7V25h-14.3V3.1zM192.8 2.9h4.6l8.2 22.1h-5l-1.5-4.6H191l-1.5 4.6h-4.9l8.2-22.1zm5.3 14.2-2.4-7.5-.6-2.3-.6 2.3-2.4 7.5h6zM216.4 2.9c2 0 4 .3 6 .9l-.7 4c-1.5-.9-3.2-1.3-5-1.3-3.6 0-6.3 2.7-6.3 7.3s2.5 7.9 6.7 7.9c1.8 0 3.5-.5 5.1-1.4v3.8c-1.7.8-3.6 1.2-5.5 1.1-6.8 0-11-4.5-11-11.1 0-7.3 4.7-11.2 10.7-11.2zM225.7 3.1h13.4v3.5h-8.8V12h6.7v3.5h-6.7v5.9h9.7V25h-14.3V3.1z"/><path class="st1" d="M80.4 39h2.5v20H92v2H80.4V39zM98 52.1c2.1-.7 4.2-1 6.4-1v-1.9c0-2.7-1.4-3.1-3.8-3.1-1.7.1-3.4.5-4.8 1.4l-.6-1.6c1.8-1 3.9-1.6 6-1.6 3.3 0 5.6.9 5.6 5v11.9h-1c-.8 0-1.3-.1-1.3-1.2v-.6c-1.4 1.2-3.2 1.8-5.1 1.8-2.9 0-5-1.7-5-4.6 0-2.1 1.3-3.6 3.6-4.5zm2.2 7.3c1.5 0 3-.5 4.2-1.4v-5.3c-1.7 0-3.4.2-5.1.8-1.6.6-2.5 1.5-2.5 3 0 1.7 1 2.9 3.4 2.9zM112 37h2.4v6.8l-.1 2.5c1.3-1.3 3.1-2 5-2 3.6 0 6.5 2.6 6.5 7.8s-3.3 9.1-8.3 9.1c-1.9 0-3.8-.4-5.5-1.2V37zm5.8 22.4c2.9 0 5.5-2.3 5.6-7 0-4.1-1.6-6.3-4.7-6.3-1.6 0-3.1.6-4.2 1.7v10.9c.9.6 2.1.8 3.3.7zM129.4 58.2c1.5.8 3.1 1.2 4.7 1.2 2.1 0 3.6-.8 3.6-2.5s-2-2.5-3.9-3.3c-2.5-1-4.7-2.4-4.7-5.1s2.7-4.1 5.7-4.2c1.5 0 2.9.3 4.2.9l-.4 1.8c-1.1-.6-2.4-.9-3.7-.9-2.4 0-3.6.9-3.6 2.2 0 1.7 1.4 2.5 3.6 3.4s5 2.2 5 5-2.2 4.5-5.7 4.5c-1.8 0-3.6-.4-5.2-1.2l.4-1.8zM7.2 31.7c0-12.2 8.9-22.6 21-24.4L27.1 0C11.6 2.4.1 15.7 0 31.5c0 6.8 2.2 13.5 6.2 19l5.8-4.3C8.9 42 7.2 36.9 7.2 31.7zM17.1 51.4l-4.2 5.7c4.2 3.1 9.1 5.1 14.2 5.9l1-7c-4-.6-7.8-2.2-11-4.6zM36.5 0l-1.1 7.3c13.5 2 22.7 14.5 20.7 28-.6 3.9-2.1 7.7-4.5 10.9l5.7 4.2c4.1-5.5 6.3-12.1 6.2-19 .1-15.7-11.4-29-27-31.4zM35.5 56l1 7c5.2-.8 10-2.8 14.2-5.9l-4.2-5.7c-3.2 2.4-7 4-11 4.6z"/></g></svg>'
|
svg: '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Layer_1" x="0" y="0" viewBox="0 0 240 63" style="enable-background:new 0 0 240 63" xml:space="preserve"><style>.st0{fill:currentColor}.st1{fill:currentColor}</style><g id="Layer_1-2"><path class="st0" d="M82.4 23.4c.4-2.3.6-4.7.5-7.1V3.1h4.6v13.1c.1 2.5 0 5-.3 7.5-.8 4.1-4.9 6-7.4 6.1l-1.1-2.4c1.9-.6 3.3-2.1 3.7-4zM92 3.1h4.5v12.3c0 5.1 1.6 6.2 4.4 6.2s4.3-1.3 4.3-6.2V3.1h4.5v12.7c0 6.1-3 9.5-8.9 9.5-6.6 0-8.8-3.8-8.8-9.6V3.1zM114 20.3c1.7.9 3.7 1.4 5.7 1.4 2.4 0 3.2-.8 3.2-2.2s-.9-2.2-4.2-3.9c-2.6-1.3-5.4-3.2-5.4-6.8 0-4.3 3.5-5.9 7.7-5.9 2-.1 3.9.4 5.7 1.3l-.8 3.6c-1.4-.9-3.1-1.4-4.7-1.4-2.4 0-3.3.9-3.3 2.2 0 1.6 1.1 2.2 3.8 3.7 3.4 1.8 6 3.4 6 7 0 4-3.1 6.1-7.5 6.1-2.3 0-4.5-.4-6.6-1.3l.4-3.8zM135.3 6.6H129V3.1h17.2v3.5h-6.3V25h-4.6V6.6zM149.4 3.1h1.4c2.4 0 4.4-.2 6.5-.2 5 0 8 2.2 8 7.6 0 5-3.1 8-8.8 8H154V25h-4.6V3.1zm7 11.8c2.2 0 4.3-.9 4.3-4.6 0-2.8-1.5-4.3-4.4-4.2-.8 0-1.6.1-2.4.2v8.4c.8.2 1.6.2 2.5.2zM168.4 3.1h13.4v3.5H173V12h6.8v3.5H173v5.9h9.7V25h-14.3V3.1zM192.8 2.9h4.6l8.2 22.1h-5l-1.5-4.6H191l-1.5 4.6h-4.9l8.2-22.1zm5.3 14.2-2.4-7.5-.6-2.3-.6 2.3-2.4 7.5h6zM216.4 2.9c2 0 4 .3 6 .9l-.7 4c-1.5-.9-3.2-1.3-5-1.3-3.6 0-6.3 2.7-6.3 7.3s2.5 7.9 6.7 7.9c1.8 0 3.5-.5 5.1-1.4v3.8c-1.7.8-3.6 1.2-5.5 1.1-6.8 0-11-4.5-11-11.1 0-7.3 4.7-11.2 10.7-11.2zM225.7 3.1h13.4v3.5h-8.8V12h6.7v3.5h-6.7v5.9h9.7V25h-14.3V3.1z"/><path class="st1" d="M80.4 39h2.5v20H92v2H80.4V39zM98 52.1c2.1-.7 4.2-1 6.4-1v-1.9c0-2.7-1.4-3.1-3.8-3.1-1.7.1-3.4.5-4.8 1.4l-.6-1.6c1.8-1 3.9-1.6 6-1.6 3.3 0 5.6.9 5.6 5v11.9h-1c-.8 0-1.3-.1-1.3-1.2v-.6c-1.4 1.2-3.2 1.8-5.1 1.8-2.9 0-5-1.7-5-4.6 0-2.1 1.3-3.6 3.6-4.5zm2.2 7.3c1.5 0 3-.5 4.2-1.4v-5.3c-1.7 0-3.4.2-5.1.8-1.6.6-2.5 1.5-2.5 3 0 1.7 1 2.9 3.4 2.9zM112 37h2.4v6.8l-.1 2.5c1.3-1.3 3.1-2 5-2 3.6 0 6.5 2.6 6.5 7.8s-3.3 9.1-8.3 9.1c-1.9 0-3.8-.4-5.5-1.2V37zm5.8 22.4c2.9 0 5.5-2.3 5.6-7 0-4.1-1.6-6.3-4.7-6.3-1.6 0-3.1.6-4.2 1.7v10.9c.9.6 2.1.8 3.3.7zM129.4 58.2c1.5.8 3.1 1.2 4.7 1.2 2.1 0 3.6-.8 3.6-2.5s-2-2.5-3.9-3.3c-2.5-1-4.7-2.4-4.7-5.1s2.7-4.1 5.7-4.2c1.5 0 2.9.3 4.2.9l-.4 1.8c-1.1-.6-2.4-.9-3.7-.9-2.4 0-3.6.9-3.6 2.2 0 1.7 1.4 2.5 3.6 3.4s5 2.2 5 5-2.2 4.5-5.7 4.5c-1.8 0-3.6-.4-5.2-1.2l.4-1.8zM7.2 31.7c0-12.2 8.9-22.6 21-24.4L27.1 0C11.6 2.4.1 15.7 0 31.5c0 6.8 2.2 13.5 6.2 19l5.8-4.3C8.9 42 7.2 36.9 7.2 31.7zM17.1 51.4l-4.2 5.7c4.2 3.1 9.1 5.1 14.2 5.9l1-7c-4-.6-7.8-2.2-11-4.6zM36.5 0l-1.1 7.3c13.5 2 22.7 14.5 20.7 28-.6 3.9-2.1 7.7-4.5 10.9l5.7 4.2c4.1-5.5 6.3-12.1 6.2-19 .1-15.7-11.4-29-27-31.4zM35.5 56l1 7c5.2-.8 10-2.8 14.2-5.9l-4.2-5.7c-3.2 2.4-7 4-11 4.6z"/></g></svg>'
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ title: peak.capital
|
||||||
header_bg_image: peak_hero_ewp1wb
|
header_bg_image: peak_hero_ewp1wb
|
||||||
order: 12
|
order: 12
|
||||||
description: Peak Capital description
|
description: Peak Capital description
|
||||||
|
tags: ['early-stage investment fund', 'venture capital', 'fund', 'investor']
|
||||||
svg: '<svg class="peak-logo-svg" xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 102 102"><style>.peak-logo-svg-circle{fill: currentColor}.peak-logo-svg-letters{fill:var(--color-bg)}</style><circle class="peak-logo-svg-circle" cx="50" cy="50" r="50"></circle><polygon class="peak-logo-svg-letters" points="70.45 39.19 70.45 61.48 75.19 61.48 75.19 53.82 78.47 50.48 84.61 61.48 90.66 61.48 82.14 46.79 89.65 39.19 83.69 39.19 75.19 47.68 75.19 39.19 70.45 39.19"></polygon><polygon class="peak-logo-svg-letters" points="43.83 43.41 43.83 39.22 28.98 39.22 28.98 61.48 43.83 61.48 43.83 57.29 33.71 57.29 33.71 52.23 43.2 52.23 43.2 48.03 33.71 48.03 33.71 43.41 43.83 43.41"></polygon><path class="peak-logo-svg-letters" d="M45.77,61.48h5.12L51.48,60a3,3,0,0,1,.16-.36,6,6,0,0,1,11-.21,2.92,2.92,0,0,1,.14.31l.7,1.78h5.15l-8.9-22.26h-5Zm13.95-9.63a10.56,10.56,0,0,0-2.53-.31,9.85,9.85,0,0,0-2.55.33l2.56-6.52Z"></path><path class="peak-logo-svg-letters" d="M9.34,39.22V61.48h4.73V53.57h3.4c5.56,0,9-2.71,9-7.18s-3.46-7.17-9-7.17Zm12.29,7.17c0,1.91-1.48,3-4.16,3h-3.4v-6h3.4C20.15,43.41,21.63,44.49,21.63,46.39Z"></path></svg>'
|
svg: '<svg class="peak-logo-svg" xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 102 102"><style>.peak-logo-svg-circle{fill: currentColor}.peak-logo-svg-letters{fill:var(--color-bg)}</style><circle class="peak-logo-svg-circle" cx="50" cy="50" r="50"></circle><polygon class="peak-logo-svg-letters" points="70.45 39.19 70.45 61.48 75.19 61.48 75.19 53.82 78.47 50.48 84.61 61.48 90.66 61.48 82.14 46.79 89.65 39.19 83.69 39.19 75.19 47.68 75.19 39.19 70.45 39.19"></polygon><polygon class="peak-logo-svg-letters" points="43.83 43.41 43.83 39.22 28.98 39.22 28.98 61.48 43.83 61.48 43.83 57.29 33.71 57.29 33.71 52.23 43.2 52.23 43.2 48.03 33.71 48.03 33.71 43.41 43.83 43.41"></polygon><path class="peak-logo-svg-letters" d="M45.77,61.48h5.12L51.48,60a3,3,0,0,1,.16-.36,6,6,0,0,1,11-.21,2.92,2.92,0,0,1,.14.31l.7,1.78h5.15l-8.9-22.26h-5Zm13.95-9.63a10.56,10.56,0,0,0-2.53-.31,9.85,9.85,0,0,0-2.55.33l2.56-6.52Z"></path><path class="peak-logo-svg-letters" d="M9.34,39.22V61.48h4.73V53.57h3.4c5.56,0,9-2.71,9-7.18s-3.46-7.17-9-7.17Zm12.29,7.17c0,1.91-1.48,3-4.16,3h-3.4v-6h3.4C20.15,43.41,21.63,44.49,21.63,46.39Z"></path></svg>'
|
||||||
---
|
---
|
||||||
Peak is an early-stage investment fund backed by entrepreneurs in Europe.
|
Peak is an early-stage investment fund backed by entrepreneurs in Europe.
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
title: Uncommonbio.co
|
title: Uncommonbio.co
|
||||||
header_bg_image: uncommon_hero_jf1in9
|
header_bg_image: uncommon_hero_jf1in9
|
||||||
order: 12
|
order: 12
|
||||||
|
tags: ['tech consultancy', 'web development', 'UX Design', 'Knoterputer', 'Henkenstein']
|
||||||
description: Peak Capital description
|
description: Peak Capital description
|
||||||
svg: '<svg id="uncommonLogo" x="0" y="0" viewBox="0 0 932 110.7" style="enable-background:new 0 0 932 110.7; fill: currentColor;"><path id="n7" class="uncommonLogo-letter" d="M828.9 3.5h30.5v9.6C865.6 4.9 878.2 0 889.3 0c10.2 0 21.6 3.1 28.1 9.1 8.4 7.5 14.7 19.9 14.7 32v66.4h-30.3V48.8c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.5V3.5z"></path><path id="o6" class="uncommonLogo-letter" d="M801.2 17.2c-10.8-10.7-24.1-16-39.6-16s-28.7 5.3-39.5 16C711.4 27.7 706 40.6 706 56c0 15.3 5.4 28.3 16.1 39 10.7 10.5 23.9 15.8 39.5 15.8s28.8-5.3 39.6-16C812 84.3 817.5 71.3 817.5 56c0-15.4-5.4-28.3-16.3-38.8zm-21.7 57.1c-4.9 5-10.8 7.5-17.9 7.5s-13-2.5-17.7-7.5c-4.9-5-7.3-11.1-7.3-18.4 0-7.2 2.4-13.4 7.1-18.4 4.9-5 10.8-7.5 17.9-7.5s13 2.5 17.9 7.5c4.9 5 7.3 11.1 7.3 18.4 0 7.3-2.5 13.4-7.3 18.4z"></path><path id="mm5" class="uncommonLogo-letter" d="M446.9 3.5h30.5v9.6C483.6 4.9 496.2 0 507.3 0c10.2 0 21.6 3.1 28.1 9.1 3.3 2.9 6.3 6.7 8.7 10.8 3.7-4.2 6.3-6.8 6.3-6.8C557.1 6.2 569.1 0 580.2 0c10.2 0 21.6 3.1 28.1 9.1 3.3 3 6.3 6.7 8.7 10.9 3.7-4.2 6.4-6.9 6.4-6.9C630.1 6.2 642.1 0 653.2 0c10.2 0 21.6 3.1 28.1 9.1 8.4 7.5 14.7 19.9 14.7 32v66.4h-30.3V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.7V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.6V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.5V3.5z"></path><path id="o4" class="uncommonLogo-letter" d="M420 17.2c-10.8-10.7-24.1-16-39.6-16s-28.7 5.3-39.5 16c-10.7 10.5-16.1 23.5-16.1 38.8 0 15.3 5.4 28.3 16.1 39 10.7 10.5 23.9 15.8 39.5 15.8s28.8-5.3 39.6-16c10.8-10.5 16.3-23.5 16.3-38.8 0-15.4-5.4-28.3-16.3-38.8zm-21.7 57.1c-4.9 5-10.8 7.5-17.9 7.5s-13-2.5-17.7-7.5c-4.9-5-7.3-11.1-7.3-18.4 0-7.2 2.4-13.4 7.1-18.4 4.9-5 10.8-7.5 17.9-7.5s13 2.5 17.9 7.5c4.9 5 7.3 11.1 7.3 18.4 0 7.3-2.4 13.4-7.3 18.4z"></path><path id="c3" class="uncommonLogo-letter" d="M247.1 16.8c10.4-10.4 23.4-15.6 39.1-15.6 13.6 0 25.5 4.5 35.6 13.4l-11.3 26.5c-6.8-7.3-14.6-11-23.2-11-7.2 0-13.2 2.5-18.1 7.5-4.9 4.9-7.3 11.2-7.3 18.9 0 7.6 2.4 13.7 7.1 18.4 4.9 4.7 10.8 7 17.9 7 8.9 0 16.7-3.7 23.6-11l11.3 26.5c-10.1 8.9-22 13.4-35.6 13.4-15.7 0-28.8-5.2-39.3-15.6-10.4-10.4-15.5-23.5-15.5-39.1s5.2-28.9 15.7-39.3z"></path><path id="n2" class="uncommonLogo-letter" d="M117.8 3.5h30.5v9.6C154.5 4.9 167.1 0 178.2 0c10.2 0 21.6 3.1 28.1 9.1 8.4 7.5 14.7 19.9 14.7 32v66.4h-30.3V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.5V3.5z"></path><path id="u1" class="uncommonLogo-letter" d="M103.1 107.2H72.6v-9.6c-6.2 8.2-18.8 13.1-29.9 13.1-10.2 0-21.6-3.1-28.1-9.1C6.3 94.1 0 81.7 0 69.6V3.2h30.3V62c0 5 1.8 12.9 4.6 15.7 2.7 2.8 6.7 6.8 16.2 6.8s14.8-4.9 17.5-8.9c2.3-3.3 4.1-7.4 4.1-13.6V3.2h30.5v104z"></path></svg>'
|
svg: '<svg id="uncommonLogo" x="0" y="0" viewBox="0 0 932 110.7" style="enable-background:new 0 0 932 110.7; fill: currentColor;"><path id="n7" class="uncommonLogo-letter" d="M828.9 3.5h30.5v9.6C865.6 4.9 878.2 0 889.3 0c10.2 0 21.6 3.1 28.1 9.1 8.4 7.5 14.7 19.9 14.7 32v66.4h-30.3V48.8c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.5V3.5z"></path><path id="o6" class="uncommonLogo-letter" d="M801.2 17.2c-10.8-10.7-24.1-16-39.6-16s-28.7 5.3-39.5 16C711.4 27.7 706 40.6 706 56c0 15.3 5.4 28.3 16.1 39 10.7 10.5 23.9 15.8 39.5 15.8s28.8-5.3 39.6-16C812 84.3 817.5 71.3 817.5 56c0-15.4-5.4-28.3-16.3-38.8zm-21.7 57.1c-4.9 5-10.8 7.5-17.9 7.5s-13-2.5-17.7-7.5c-4.9-5-7.3-11.1-7.3-18.4 0-7.2 2.4-13.4 7.1-18.4 4.9-5 10.8-7.5 17.9-7.5s13 2.5 17.9 7.5c4.9 5 7.3 11.1 7.3 18.4 0 7.3-2.5 13.4-7.3 18.4z"></path><path id="mm5" class="uncommonLogo-letter" d="M446.9 3.5h30.5v9.6C483.6 4.9 496.2 0 507.3 0c10.2 0 21.6 3.1 28.1 9.1 3.3 2.9 6.3 6.7 8.7 10.8 3.7-4.2 6.3-6.8 6.3-6.8C557.1 6.2 569.1 0 580.2 0c10.2 0 21.6 3.1 28.1 9.1 3.3 3 6.3 6.7 8.7 10.9 3.7-4.2 6.4-6.9 6.4-6.9C630.1 6.2 642.1 0 653.2 0c10.2 0 21.6 3.1 28.1 9.1 8.4 7.5 14.7 19.9 14.7 32v66.4h-30.3V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.7V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.6V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.5V3.5z"></path><path id="o4" class="uncommonLogo-letter" d="M420 17.2c-10.8-10.7-24.1-16-39.6-16s-28.7 5.3-39.5 16c-10.7 10.5-16.1 23.5-16.1 38.8 0 15.3 5.4 28.3 16.1 39 10.7 10.5 23.9 15.8 39.5 15.8s28.8-5.3 39.6-16c10.8-10.5 16.3-23.5 16.3-38.8 0-15.4-5.4-28.3-16.3-38.8zm-21.7 57.1c-4.9 5-10.8 7.5-17.9 7.5s-13-2.5-17.7-7.5c-4.9-5-7.3-11.1-7.3-18.4 0-7.2 2.4-13.4 7.1-18.4 4.9-5 10.8-7.5 17.9-7.5s13 2.5 17.9 7.5c4.9 5 7.3 11.1 7.3 18.4 0 7.3-2.4 13.4-7.3 18.4z"></path><path id="c3" class="uncommonLogo-letter" d="M247.1 16.8c10.4-10.4 23.4-15.6 39.1-15.6 13.6 0 25.5 4.5 35.6 13.4l-11.3 26.5c-6.8-7.3-14.6-11-23.2-11-7.2 0-13.2 2.5-18.1 7.5-4.9 4.9-7.3 11.2-7.3 18.9 0 7.6 2.4 13.7 7.1 18.4 4.9 4.7 10.8 7 17.9 7 8.9 0 16.7-3.7 23.6-11l11.3 26.5c-10.1 8.9-22 13.4-35.6 13.4-15.7 0-28.8-5.2-39.3-15.6-10.4-10.4-15.5-23.5-15.5-39.1s5.2-28.9 15.7-39.3z"></path><path id="n2" class="uncommonLogo-letter" d="M117.8 3.5h30.5v9.6C154.5 4.9 167.1 0 178.2 0c10.2 0 21.6 3.1 28.1 9.1 8.4 7.5 14.7 19.9 14.7 32v66.4h-30.3V48.7c0-5-1.8-12.9-4.6-15.7-2.7-2.8-6.7-6.8-16.2-6.8s-14.8 4.9-17.5 8.9c-2.3 3.3-4.1 7.4-4.1 13.6v58.8h-30.5V3.5z"></path><path id="u1" class="uncommonLogo-letter" d="M103.1 107.2H72.6v-9.6c-6.2 8.2-18.8 13.1-29.9 13.1-10.2 0-21.6-3.1-28.1-9.1C6.3 94.1 0 81.7 0 69.6V3.2h30.3V62c0 5 1.8 12.9 4.6 15.7 2.7 2.8 6.7 6.8 16.2 6.8s14.8-4.9 17.5-8.9c2.3-3.3 4.1-7.4 4.1-13.6V3.2h30.5v104z"></path></svg>'
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -1,76 +1,108 @@
|
||||||
|
.works-wrapper {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 16vw;
|
font-size: 16vw;
|
||||||
font-style: italic;
|
margin: var(--spacing-nav) var(--spacing-nav) .25em var(--spacing-nav);
|
||||||
margin: 0 0 0.5em 0;
|
padding: 0 0 calc(var(--spacing-nav) / 3) 0;
|
||||||
letter-spacing: -0.04em;
|
position: relative;
|
||||||
text-align: center;
|
z-index: -1;
|
||||||
position: fixed;
|
|
||||||
top: calc(50svh - 16vw);
|
|
||||||
width: 100%;
|
|
||||||
visibility: hidden;
|
|
||||||
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
font-size: 7vw;
|
font-size: 7vw;
|
||||||
top: calc(50svh - 3.5vw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
& span {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0 0.25em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
line-height: 1.1;
|
|
||||||
letter-spacing: -0.025em;
|
|
||||||
font-size: 2.5vw;
|
|
||||||
opacity: 0;
|
|
||||||
position: absolute;
|
|
||||||
left: .5em;
|
|
||||||
bottom: .5em;
|
|
||||||
transform: scale(0.8) translateY(100%);
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.1em 0.4em 0.2em 0.4em;
|
|
||||||
text-align: center;
|
|
||||||
transform-origin: center center;
|
|
||||||
width: auto;
|
|
||||||
margin: 0;
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
color: var(--color-text);
|
|
||||||
transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
||||||
|
|
||||||
.works .work:not(.active):hover & {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1) translateY(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.works {
|
.works {
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.25em;
|
gap: 0.25em;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
gap: 0.25em;
|
display: grid;
|
||||||
padding: 8.5vw 0.5em 0.5em 0.5em;
|
grid-template-columns: repeat(3, 1fr);
|
||||||
width: 100%;
|
gap: 1px;
|
||||||
max-width: 1200px;
|
padding: 0 var(--spacing-nav);
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding-bottom: 20svh;
|
padding-bottom: 20svh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.work-info,
|
||||||
|
.work:visited .work-info {
|
||||||
|
position: absolute;
|
||||||
|
left: 0.25em;
|
||||||
|
top: 0.25em;
|
||||||
|
padding: 0.5em .75em;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: var(--color-text);
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
& h2 {
|
||||||
|
text-transform: none;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 1.2em;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
line-height: 1;
|
||||||
|
visibility: hidden;
|
||||||
|
color: var(--color-bg);
|
||||||
|
}
|
||||||
|
& .tags {
|
||||||
|
visibility: hidden;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 10px 0 0 0 ;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.15em;
|
||||||
|
transition: all .4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
}
|
||||||
|
& .tag {
|
||||||
|
font-size: .6em;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
// font-weight: 800;
|
||||||
|
// font-style: italic;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.work:hover .work-info {
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
& h2 {
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
.work {
|
.work {
|
||||||
flex: 0 0 calc(50% - 0.125em );
|
flex: 0 0 calc(50% - 0.125em );
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
// transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
flex: 0 0 calc(33% - .125em);
|
grid-column-end: span 1;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
grid-column-end: span 2;
|
||||||
|
grid-row-end: span 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.work .tag {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
:global(.work img) {
|
:global(.work img) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|
|
||||||
|
|
@ -8,38 +8,97 @@ workbulge.subscribe(value => {
|
||||||
bulge.factor = value;
|
bulge.factor = value;
|
||||||
})
|
})
|
||||||
|
|
||||||
export function initWorkPage( h1: HTMLElement, canvasImgElems: Array<HTMLElement>) {
|
export function initWorkPage( canvasTextElems: Array<HTMLElement>, canvasImgElems: Array<HTMLElement>) {
|
||||||
|
|
||||||
workbulge.set(0.25);
|
workbulge.set(0);
|
||||||
|
|
||||||
|
gsap.to(bulge, {
|
||||||
|
duration: .5,
|
||||||
|
factor: 0.15,
|
||||||
|
delay: .8,
|
||||||
|
ease: 'back.out(3)',
|
||||||
|
onUpdate: () => {
|
||||||
|
workbulge.set(bulge.factor);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const workinfos: Array<HTMLElement> = Array.from(document.querySelectorAll('.work-info'));
|
||||||
|
|
||||||
|
workinfos.forEach((workinfo) => {
|
||||||
|
|
||||||
|
const workinfoTitle = workinfo.querySelector('h2') as HTMLElement;
|
||||||
|
const workinfoTitleWords = workinfoTitle.querySelector('span') as HTMLElement;
|
||||||
|
|
||||||
|
const expanded = {
|
||||||
|
height: workinfo.getBoundingClientRect().height,
|
||||||
|
width: workinfo.getBoundingClientRect().width + 2,
|
||||||
|
paddingTop: Number(window.getComputedStyle(workinfo).paddingTop.replace('px','')) as number,
|
||||||
|
paddingLeft: Number(window.getComputedStyle(workinfo).paddingLeft.replace('px','')) as number,
|
||||||
|
}
|
||||||
|
|
||||||
|
const contracted = {
|
||||||
|
height: workinfoTitle.offsetHeight * 1.2 + 2 * expanded.paddingTop,
|
||||||
|
width: workinfoTitleWords.offsetWidth + 2 * expanded.paddingLeft,
|
||||||
|
}
|
||||||
|
|
||||||
|
workinfo.style.width = `${contracted.width}px`;
|
||||||
|
workinfo.style.height = `${contracted.height}px`;
|
||||||
|
const tags = workinfo.querySelector('.tags') as HTMLElement;
|
||||||
|
tags.style.width = `${expanded.width}px`;
|
||||||
|
|
||||||
|
workinfo.parentElement?.addEventListener('mouseenter', () => {
|
||||||
|
gsap.to(workinfo, {
|
||||||
|
duration: .25,
|
||||||
|
width: expanded.width,
|
||||||
|
height: expanded.height,
|
||||||
|
ease: 'power2.inOut',
|
||||||
|
overwrite: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
workinfo.parentElement?.addEventListener('mouseleave', () => {
|
||||||
|
gsap.to(workinfo, {
|
||||||
|
duration: .25,
|
||||||
|
width: contracted.width,
|
||||||
|
height: contracted.height,
|
||||||
|
ease: 'power2.inOut',
|
||||||
|
overwrite: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
gsap.registerPlugin( SplitText );
|
gsap.registerPlugin( SplitText );
|
||||||
|
|
||||||
const h1Text = h1?.innerHTML || '';
|
const work = document.querySelectorAll('.work');
|
||||||
h1.innerHTML = h1Text + h1Text + h1Text + h1Text || '';
|
gsap.set(document.querySelectorAll('.tag'), {opacity: 0, yPercent: 200});
|
||||||
h1.style.overflow = 'hidden';
|
gsap.set(document.querySelectorAll('h2'), {opacity: 1 });
|
||||||
h1.style.whiteSpace = 'nowrap';
|
work.forEach((el) => {
|
||||||
const spans = Array.from(h1.querySelectorAll('span'));
|
el.addEventListener('mouseenter', (e) => {
|
||||||
spans.forEach((span, index) => {
|
const target = e.target as HTMLElement;
|
||||||
gsap.set(span, { opacity: 1, y: -window.innerHeight/1.5 })
|
gsap.to(target?.querySelectorAll('.tag'), {duration: 0.5, opacity: 1, yPercent: 0, ease: 'back.out(1.7)', stagger: 0.025, overwrite: true});
|
||||||
gsap.to(span, { opacity: 1, y: 0, duration: 1, ease: 'power3.out', delay: index * 0.025 })
|
gsap.to(target?.querySelector('h2'), {duration: 0.5, opacity: 1, ease: 'back.out(1.7)', overwrite: true});
|
||||||
gsap.to(span, { xPercent: -100, duration: 4, ease: 'none', repeat: -1 })
|
});
|
||||||
|
el.addEventListener('mouseleave', (e) => {
|
||||||
|
const target = e.target as HTMLElement;
|
||||||
|
gsap.to(target?.querySelectorAll('.tag'), {duration: 0.3, opacity: 0, yPercent: 200, ease: 'power2.out', overwrite: true});
|
||||||
|
gsap.to(target?.querySelector('h2'), {duration: 0.5, opacity: 1, ease: 'back.out(1.7)', overwrite: true});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
gsap.set(canvasImgElems, {
|
gsap.set('.work', {
|
||||||
opacity: 0, yPercent: 50
|
opacity: 0, yPercent: 50
|
||||||
})
|
})
|
||||||
|
|
||||||
gsap.to(canvasImgElems, {
|
gsap.to('.work', {
|
||||||
duration: 1,
|
duration: 1,
|
||||||
opacity: .8,
|
opacity: 1,
|
||||||
yPercent: 0,
|
yPercent: 0,
|
||||||
stagger: 0.05,
|
stagger: 0.05,
|
||||||
ease: 'elastic.out(0.75, 0.5)',
|
ease: 'elastic.out(0.75, 0.5)',
|
||||||
delay: 0.3
|
delay: 0.3,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text: spans,
|
text: canvasTextElems,
|
||||||
images: canvasImgElems
|
images: canvasImgElems
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -67,12 +126,30 @@ export function workClickHandler(e:Event){
|
||||||
|
|
||||||
document.body.appendChild(coverclone);
|
document.body.appendChild(coverclone);
|
||||||
|
|
||||||
|
gsap.to('.work .work-info', {
|
||||||
|
duration: .3,
|
||||||
|
opacity: 0,
|
||||||
|
yPercent: -10,
|
||||||
|
ease: 'power4.out',
|
||||||
|
})
|
||||||
gsap.to('.work:not(.active) img', {
|
gsap.to('.work:not(.active) img', {
|
||||||
duration: .3,
|
duration: .3,
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
yPercent: 10,
|
yPercent: 20,
|
||||||
ease: 'power4.out',
|
ease: 'power4.out',
|
||||||
})
|
})
|
||||||
|
gsap.to('.work h2', {
|
||||||
|
duration: .3,
|
||||||
|
opacity: 0,
|
||||||
|
// scale: 0,
|
||||||
|
ease: 'power3.out'
|
||||||
|
})
|
||||||
|
gsap.to('.work .tag', {
|
||||||
|
duration: .3,
|
||||||
|
opacity: 0,
|
||||||
|
// scale: 0,
|
||||||
|
ease: 'power3.out'
|
||||||
|
})
|
||||||
gsap.set(targetImg, {
|
gsap.set(targetImg, {
|
||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
274
static/cursor.ai
Normal file
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 50" style="enable-background:new 0 0 40 50" xml:space="preserve" width="40" height="50"><path style="fill:#ff9494;stroke:#00117f;stroke-width:3;stroke-miterlimit:10" d="M5.4 5 5 44.6l13.1-10.9L35 31.2z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 50" width="40" height="50" style="enable-background:new 0 0 40 50" xml:space="preserve"><path d="M2.4 5 2 46.8l15.8-13.6 14.2-2L2.4 5z" style="opacity:.5"/><path d="M5.4 0 5 39.6l13.1-10.9L35 26.2 5.4 0z" style="fill:#fff"/></svg>
|
||||||
|
Before Width: | Height: | Size: 266 B After Width: | Height: | Size: 286 B |
BIN
static/home/about-portrait-opt-1200.WEBP
Normal file
|
After Width: | Height: | Size: 24 KiB |
291
static/home/creative-dev.ai
Normal file
1
static/home/creative-dev.svg
Normal file
|
After Width: | Height: | Size: 406 KiB |
1070
static/home/design-shapes.ai
Normal file
BIN
static/home/simon-hicon.png
Normal file
|
After Width: | Height: | Size: 600 KiB |
BIN
static/home/simon-portrait.png
Normal file
|
After Width: | Height: | Size: 186 KiB |
40
static/home/world-graph.svg
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 2000 1000" width="2000" height="1000" style="enable-background:new 0 0 2000 1000;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:var(--color-text, #FFF);}
|
||||||
|
.st1{fill:var(--color-highlight, #000);}
|
||||||
|
</style>
|
||||||
|
<g id="keys">
|
||||||
|
<polygon class="st0" points="174.3,857.9 85.6,857.9 44.8,898.7 44.8,930.6 133.5,930.6 174.3,889.7 "/>
|
||||||
|
<polygon class="st0" points="299.5,857.9 210.8,857.9 170,898.7 170,930.6 258.7,930.6 299.5,889.7 "/>
|
||||||
|
<polygon class="st0" points="257.3,812.6 257.3,780.7 168.6,780.7 127.8,821.6 127.8,853.4 216.5,853.4 "/>
|
||||||
|
<polygon class="st0" points="382.6,780.7 293.9,780.7 253.1,821.6 253.1,853.4 341.8,853.4 382.6,812.6 "/>
|
||||||
|
<polygon class="st0" points="423.4,857.9 334.7,857.9 293.9,898.7 293.9,930.6 382.6,930.6 423.4,889.7 "/>
|
||||||
|
<polygon class="st0" points="419.2,898.7 419.2,930.6 507.9,930.6 548.7,889.7 548.7,857.9 460,857.9 "/>
|
||||||
|
<polygon class="st0" points="506.5,812.6 506.5,780.7 417.8,780.7 376.9,821.6 376.9,853.4 465.6,853.4 "/>
|
||||||
|
<polygon class="st0" points="502.2,821.6 502.2,853.4 590.9,853.4 631.7,812.6 631.7,780.7 543,780.7 "/>
|
||||||
|
<polygon class="st0" points="337.5,735.4 337.5,703.6 248.8,703.6 208,744.4 208,776.2 296.7,776.2 "/>
|
||||||
|
<polygon class="st0" points="333.3,776.2 422,776.2 462.8,735.4 462.8,703.6 374.1,703.6 333.3,744.4 "/>
|
||||||
|
<polygon class="st0" points="457.2,776.2 545.9,776.2 586.7,735.4 586.7,703.6 498,703.6 457.2,744.4 "/>
|
||||||
|
<polygon class="st0" points="623.3,703.6 582.4,744.4 582.4,776.2 671.1,776.2 712,735.4 712,703.6 "/>
|
||||||
|
<polygon class="st0" points="409.6,624.6 320.9,624.6 280.1,665.4 280.1,697.2 368.8,697.2 409.6,656.4 "/>
|
||||||
|
<polygon class="st0" points="534.9,624.6 446.2,624.6 405.4,665.4 405.4,697.2 494.1,697.2 534.9,656.4 "/>
|
||||||
|
<polygon class="st0" points="492.7,579.2 492.7,547.4 404,547.4 363.1,588.2 363.1,620.1 451.8,620.1 "/>
|
||||||
|
<polygon class="st0" points="617.9,547.4 529.2,547.4 488.4,588.2 488.4,620.1 577.1,620.1 617.9,579.2 "/>
|
||||||
|
<polygon class="st0" points="658.8,624.6 570.1,624.6 529.2,665.4 529.2,697.2 617.9,697.2 658.8,656.4 "/>
|
||||||
|
<polygon class="st0" points="654.5,665.4 654.5,697.2 743.2,697.2 784,656.4 784,624.6 695.3,624.6 "/>
|
||||||
|
<polygon class="st0" points="741.8,579.2 741.8,547.4 653.1,547.4 612.3,588.2 612.3,620.1 701,620.1 "/>
|
||||||
|
<polygon class="st0" points="737.5,588.2 737.5,620.1 826.2,620.1 867.1,579.2 867.1,547.4 778.4,547.4 "/>
|
||||||
|
<polygon class="st0" points="572.9,502.1 572.9,470.2 484.2,470.2 443.4,511.1 443.4,542.9 532.1,542.9 "/>
|
||||||
|
<polygon class="st0" points="568.6,542.9 657.3,542.9 698.2,502.1 698.2,470.2 609.5,470.2 568.6,511.1 "/>
|
||||||
|
<polygon class="st0" points="692.5,542.9 781.2,542.9 822,502.1 822,470.2 733.3,470.2 692.5,511.1 "/>
|
||||||
|
<polygon class="st0" points="858.6,470.2 817.8,511.1 817.8,542.9 906.5,542.9 947.3,502.1 947.3,470.2 "/>
|
||||||
|
</g>
|
||||||
|
<path id="thumb" class="st1" d="M936.6,532.9l-135.2,67l-72.1,144l73,46.7l94-110.3l274.7,19.6l-1-33.6
|
||||||
|
c-2.3-75.9-65.1-135.9-141-134.7L936.6,532.9z"/>
|
||||||
|
<polygon id="pinky" class="st1" points="1022.9,403.8 852.1,470.6 874.4,550.7 815.7,548.9 759.3,452.9 912.1,280.3 1103.5,390.8
|
||||||
|
"/>
|
||||||
|
<polygon id="ring" class="st1" points="1085.9,295.4 720.3,385.9 685.7,501.8 672.5,595.7 739.6,603.4 780.8,472.9 877.5,385.9 "/>
|
||||||
|
<polygon id="middle" class="st1" points="885.6,264.5 714.6,325.1 606.2,432.2 542.3,613.8 610.1,643.8 691.5,487.9 812.3,386.2 1089,341.4"/>
|
||||||
|
<path id="index" class="st1" d="M982.1,260.2L754.4,128.7L566.8,235.9l-47.1,169.9l65.1,23.6L647.8,310l91-39.9l145.6,129l59.2-7.2 c38.8-4.7,64.2-43.1,53.3-80.6L982.1,260.2z"/>
|
||||||
|
<path id="arm" class="st1" d="M1170.9,699.7l254-87.9l87.9-78.2l491.7-306.1L1779.9,51.8l-358.2,276.8l-439.6-68.4l-39.4,1.3 c-48.9,1.6-83.4,48.7-70.1,95.8l11.8,41.8l52.2,133.8l28.1,88L1170.9,699.7z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.8 KiB |
314
static/pointer.ai
Normal file
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 50" style="enable-background:new 0 0 40 50" xml:space="preserve" width="40" height="50"><path d="m17.2 12.2-5.7-8.1c-1.3-1.9-3.9-2.3-5.7-1l-.2.2C3.7 4.6 3.3 7.2 4.6 9l6.3 8.9c-3 1.7-2.4 4.8-2.4 4.8-2.2.8-3.2 2.4-3 4.8 0 0-3.9 2.1-3.1 6.1l6.4 9.1c3.5 5 10.4 6.2 15.3 2.7l4.6-3.3c3-2.1 4.7-5.5 4.7-9.1-.1-6.1 1-8.2-2-13.5l-4-9.6c-.6-1.1-1.8-1.6-3-1.3l-.7.2c-1.2.3-2 1.4-2 2.6l.4 7.6-4.9-6.8z" style="fill:#ff9494;stroke:#00117f;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:10"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 50" width="40" height="50" style="enable-background:new 0 0 40 50" xml:space="preserve"><path d="M15.1 12.5 9.4 3.8c-1.3-2-3.9-2.5-5.7-1.1l-.2.3c-1.9 1.3-2.3 4.1-1 6l5.3 8.5c-3 1.8-2.4 5.1-2.4 5.1-2.2.9-3.2 2.6-3 5.1 0 0-2.9 3.2-2.1 7.5L6.7 45c3.5 5.3 10.4 6.6 15.3 2.9l4.6-3.5c3-2.2 4.7-5.9 4.7-9.7-.1-6.5 1-8.7-2-14.4L25.3 8c-.6-1.2-1.8-1.7-3-1.4l-.7.2c-1.2.3-2 1.5-2 2.8l.4 10.1-4.9-7.2z" style="opacity:.5"/><path d="M15.8 10.3 9.2 2.9C7.7 1.2 5.1 1 3.4 2.5l-.1.2c-1.8 1.5-1.9 4.2-.4 5.8l7.2 8.2c-2.8 2-1.9 5-1.9 5-2.1 1-2.9 2.7-2.5 5.1 0 0-3.7 2.5-2.4 6.4l7.3 8.4c4 4.6 11 5.1 15.5 1.1l4.2-3.8c2.8-2.4 4.1-6 3.7-9.6-.8-6.1.1-8.3-3.4-13.2l-5-9.1c-.7-1-2-1.4-3.1-1l-.7.3c-1.2.4-1.8 1.6-1.7 2.8l1.2 7.5-5.5-6.3z" style="fill:#fff"/></svg>
|
||||||
|
Before Width: | Height: | Size: 548 B After Width: | Height: | Size: 796 B |