Why Create a Private Portfolio?
Contemplating I’m already the co-founder of Overpx studio, it is a query many may ask. The explanations are primarily two:
1. The necessity for a private house: from 2008 to 2014 I had a weblog, fedeweb.internet, the place I used to jot down articles about WordPress, JavaScript, Gimp (does it nonetheless exist?), and extra. After closing it, I’ve missed having an area of my very own to share concepts and initiatives.
2. A private problem: I needed to problem myself by dealing with on my own each step of the method, from idea to execution. I took care of every stage: ideation, moodboard, design and growth, with out counting on anybody else.
Earlier than beginning the design course of, I took the Obys course on Awwwards, which I extremely advocate. It supplied helpful insights and helped me refine my design strategy.
Inspiration
I’ve all the time been drawn in direction of geometry, particularly circles, precision, and cleanliness in design. Whereas gathering parts for my moodboard, I discovered two specific pictures on Savee that had a major impression on the general design of the location, shaping its visible course.
Attempt to guess what parts have been influenced by these pictures 🙂
Improvement
The first purpose throughout the growth section was to make sure a clean, uninterrupted expertise whereas navigating between pages. I needed to keep away from any pauses or delays, making a seamless stream all through the whole web site.
The tech stack
I used my typical growth stack, with one key exception: as an alternative of utilizing a CMS for content material administration, I opted to deal with the whole lot instantly through a JSON file.
Web page transitions
To deal with the transitions between pages and initiatives, I began with this Stackblitz supplied by GSAP, particularly developed for Nuxt 3.
The transitions range relying on each the present web page and the vacation spot web page. To handle the totally different instances, I examine the worth of the clicked aspect with the present route.
The clicked aspect worth is managed by the routeStore state, created with Pinia, the place a customized worth is handed.
// strategies navigate for the following mission hyperlink, inside a single mission web page
const navigate = (e) => {
const route = e.currentTarget.dataset.url
routeStore.setUrl('/projects-single') // set the routeStore worth
navigateTo({ path: route })
}
The present route is retrieved utilizing the useRoute() composable supplied by Nuxt.
These two values are in contrast throughout the onLeave occasion of the web page. Let’s take a more in-depth take a look at the transition between initiatives:
onLeave: (el, performed) => {
const routeStore = useUrlStore(),
route = useRoute()
// different circumstances
// from single to single
if (route.title === 'projects-single' && routeStore.url === '/projects-single') {
// ...
const elementToFlip = el.querySelector('[data-next-project]')
useFlipState().worth = Flip.getState(elementToFlip)
// ...
}
// different circumstances
},
As you’ll be able to see, I used Flip, a GSAP plugin that enables to handle seamlessly transition between two states.
Particularly, the aspect to flip is handed to the getState() perform. The worth is then assigned to the useFlipState composable so it may be reused on the vacation spot web page.
// composable useFlipState.js
export const useFlipState = () => useState('flip-state');
Lastly, inside the single mission web page, the transition between the 2 states is carried out utilizing Flip.from:
const flipTl = Flip.from(useFlipState().worth, {
targets: pictureEls[0], // get the primary picture of the gallery
period: 1.2,
z: 0,
ease: 'power3.out',
// ...
})
// border radius animation
flipTl.fromTo(
pictureEls[0], // first gallery merchandise
{ '--borderRadius': isDesktop ? '20rem' : '10rem' },
{ '--borderRadius': isDesktop ? '2rem' : '2rem', period: 0.6, ease: 'sine.out' },
0
)
// ...
Flip.from() returns a timeline the place you’ll be able to add all the opposite animations you want within the transition; within the code instance there may be the border-radius animation.
Textual content impact
The purpose was to include the idea of a diagonal into the textual content animations, making a dynamic and visually attention-grabbing motion.
To realize this impact, I used the SplitText plugin to separate the textual content into particular person characters, after which I utilized a clipPath together with a diagonal transition (each x and y) for the all pages besides the homepage, the place there’s a horizontal-only transition.
Particularly, I created a world animation, clipTitle, which was then known as wherever wanted:
gsap.registerEffect({
title: 'clipTitle',
impact: (targets, config) => {
const tl = gsap.timeline({
defaults: { period: config.period, ease: config.ease },
})
// Test if the textual content has already been break up, if not, break up it and mark it as performed
const chars = targets[0].classList.incorporates('text-split-done')
? targets[0].querySelectorAll('.char')
: new SplitText(targets, { sort: 'chars', charsClass: 'char' }).chars
if (!targets[0].classList.incorporates('text-split-done')) {
targets[0].classList.add('text-split-done')
}
tl.fromTo(
chars,
{
x: config.x,
yPercent: config.yPercent,
clipPath: 'inset(0% 100% 120% -5%)',
transformOrigin: '0% 50%',
},
{
willChange: 'rework',
clipPath: 'inset(0% -100% -100% -5%)',
x: 0,
yPercent: 0,
stagger: config.stagger,
period: config.period,
ease: config.ease,
},
0.05
)
return tl
},
defaults: { yPercent: 30, x: -30, period: 0.8, ease: 'power3.out', stagger: -0.05 },
extendTimeline: true,
})
Background animation
For the background animation, I used TresJs, a library that enables creating ThreeJS scenes with Vue elements in a declarative manner. Whereas I may have used ThreeJS instantly or one other WebGL library, I made a decision to go together with TresJs to try it out and discover its capabilities.
That is the fragment shader for the background distortion:
float circle_s(vec2 dist,float radius){
return smoothstep(0.,radius,pow(dot(dist,dist),.6)*.1);
}
void important(){
vec2 facet=vec2(u_resolution.x/u_resolution.y,1.);
vec2 uv=vUv*facet;
vec2 mouse=vUv-u_point;
mouse.y/=u_ratio;
float noise=snoise(vec3(uv,u_time * 3.));
float noise1=snoise(vec3(uv+.1,u_time * 3.));
float noise2=snoise(vec3(uv-.1,u_time * 3.));
float alpha=(noise+noise1+noise2)/3.;
alpha*=circle_s(mouse,.015 * u_mouseInteraction);
float x=1.-noise;
vec3 color1=vec3(u_color1.x/255.,u_color1.y/255.,u_color1.z/255.);
vec3 color2=vec3(u_color2.x/255.,u_color2.y/255.,u_color2.z/255.);
// Mixing primarily based on mixed noise
float blendFactor=smoothstep(.1,1.,x * 1.);
vec3 blendedColor=combine(color1, color2, blendFactor);
gl_FragColor.rgb=blendedColor;
gl_FragColor.a=alpha;
}
The snoise perform will be discovered on this gist, specifically I used the Simplex3D noise by Ian McEwan and Stefan Gustavson and it was used to create a form of colour distortion impact by manipulating the alpha element.
The colours are managed by a state created with Pinia, which receives the colours in rgb format, from a JSON file.
Keyboard-only utilization
One factor I’m notably happy with is that the whole web site is totally navigable utilizing solely the keyboard. This contains the mission web page, the place you’ll be able to entry particular person initiatives utilizing digit numbers, and inside the single mission pages, you’ll be able to navigate from one mission to the following utilizing the appropriate arrow key.
Different tech points
For the mouse path impact, I began with this Codrops playground (thanks, Manoela! 😊) and tailored it to go well with my particular use case.
For the scrolling impact on the initiatives web page, I primarily based it on this CodePen created by GSAP, additional customizing it to match the location’s stream and interplay.
404 web page
I tried to simulate the impact of Newton’s cradle, with the colours of the shader altering randomly every time.
Sounds results
In 2022, I got here throughout this sound library and promised myself I’d use it in a mission sometime. What higher alternative than to make use of it for my very own web site?
The library incorporates three sound collections, and on the location, I particularly used a number of sounds from the “sine” assortment.
Conclusions
This mission has been a satisfying expertise of self-expression and technical exploration. I realized rather a lot about crafting seamless net experiences, and I’m excited to use these classes to future initiatives.
I’m very grateful for all of the appreciation and awards obtained. Profitable my first SOTD on Awwwards has been a real spotlight of this journey, it feels type of unbelievable.
I hope you loved this behind-the-scenes take a look at my portfolio mission, maybe it might encourage you to your personal work.