Direction artistique, UI/UX et développement d’un prototype de portfolio pour un studio de production vidéo.

Concept

L’idée est d’avoir une pile d’images, positionnées selon la position du curseur par rapport au centre de l’écran, toutes plus décalées et floutées.

Des images les unes par dessus les autres, alignées en diagonale.

Technique

Explication

Schéma représentant un écran. Le curseur est en haut à gauche de celui-ci, des lignes mesures sa distance horizontale et verticale par rapport au centre de l’écran.
1. On repère d’abord où se trouve le curseur par rapport au centre de l’écran.
Des rectangles sont positionnés avec d’autres lignes de distance, avec les formules ci-dessous.
2. On place les images en déterminant leurs positions avec cette formule pour x et y.
sommet.tsx
x = distanceX + index * (distanceX / total);
y = distanceY + index * (distanceY / total);
Les variables dans la formule sont remplacées par leurs valeurs, et on obtient les coordonnées des images.
3. Si l’on a 5 images, on obtient ces résultats pour les images 0, 2 et 4.
4. Chaque image est positionnée correctement, leur position évoluera en fonction de la distance du curseur par rapport au centre de l’écran.

Code

Pour accentuer l’effet de profondeur, j’ai rétréci et flouté chaque image selon son éloignement. Pour renforcer la perception du mouvement, l’éloignement de l’image affecte également sa vitesse de déplacement.

Voici, en résumé, le composant permettant de réaliser tout ceci.

sommet.tsx
// Déterminer la distance de la souris par rapport au centre
const distanceX = mousePosition.x - windowCenter.x;
const distanceY = mousePosition.y - windowCenter.y;
return (
<div>
{projects.map((project, index) => {
// Changer l’index dynamiquement
const fluidIndex =
(index - activeProject + totalProjects) % totalProjects;
return (
<Image
{...}
src={project.image}
style={{
// Définir les coordonnées d’origine
top: windowCenter.y,
left: windowCenter.x,
// Calculer tailles et décalages de chaque image
// par rapport à son index
transform: `
translateX(${distanceX + ((fluidIndex * (distanceX / totalProjects)) % windowCenter.x)}px)
translateY(${distanceY + ((fluidIndex * (distanceY / totalProjects)) % windowCenter.y)}px)
scale(1.${totalProjects - fluidIndex})`,
// Plus l’image est en arrière plus elle est floue…
filter: `blur(${fluidIndex * 0.4}px)`,
// …Et lente dans ses déplacements
transitionDuration: `${fluidIndex * 0.1}s`,
transitionProperty: "transform",
zIndex: -fluidIndex + totalProjects
}}
/>
);
})}
</div>
);

Résultat

Crédits

Typographie

Vidéos