Add animated menu cards

This commit is contained in:
2025-10-30 14:54:32 +01:00
parent 693484d44c
commit 41cdb5837d
7 changed files with 230 additions and 80 deletions

View File

@@ -11,7 +11,7 @@
<link rel="stylesheet" href="./styles/style.css"> <link rel="stylesheet" href="./styles/style.css">
<link rel="stylesheet" href="./styles/introduction.css"> <link rel="stylesheet" href="./styles/introduction.css">
<link rel="stylesheet" href="./styles/projects.css"> <link rel="stylesheet" href="styles/projects.css">
<title>Naaturel</title> <title>Naaturel</title>
@@ -32,7 +32,34 @@
</section> </section>
<section id="projects"> <section id="projects">
<div class="content"> <div class="card-list">
<a>
<div class="card">
<h2>My <span class="accentuated">projects</span></h2>
<hr/>
<p>Get a look at what I've worked on</p>
</div>
</a>
<a>
<div class="card">
<h2><span class="accentuated">About</span> me</h2>
<hr/>
<p>Learn more about my skills and background</p>
</div>
</a>
<a>
<div class="card">
<h2><span class="accentuated">Contacts</span></h2>
<hr/>
<p>Get in touch with me</p>
</div>
</a>
</div>
<!--<div class="content">
<div > <div >
<h1>Live projects</h1> <h1>Live projects</h1>
<hr/> <hr/>
@@ -54,7 +81,7 @@
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>-->
</section> </section>
</main> </main>
@@ -71,4 +98,14 @@
typer.start(); typer.start();
</script> </script>
<script type="module">
import {CardTilter} from "./scripts/CardTilter.js";
const cards = document.querySelectorAll('.card');
cards.forEach(card => { new CardTilter({card : card, tilt : 15, perspective : 650}) })
</script>
</html> </html>

10
html/projects.html Normal file
View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,48 @@
export class CardTilter {
/**
*
* @param card Card to be moved
* @param tilt max tilting angle in degree
* @param perspective perspective in pixels
*/
constructor({card : card, tilt : tilt, perspective : perspective}) {
this.card = card;
this.tilt = tilt;
this.perspective = perspective;
this.watch()
}
watch(){
this.card.addEventListener('mousemove', (e) => {
const rotations = this.calculatePositions(e.clientX, e.clientY);
this.transform(rotations.x, rotations.y);
});
this.card.addEventListener('mouseleave', () => {
this.reset();
});
}
calculatePositions(cursorX, cursorY) {
const rect = this.card.getBoundingClientRect();
const x = cursorX - rect.left;
const y = cursorY - rect.top;
const percentX = (x / rect.width) - 0.5;
const percentY = (y / rect.height) - 0.5;
const rotateX = -percentY * this.tilt;
const rotateY = percentX * this.tilt;
return {x : rotateX, y : rotateY};
};
transform(rotationX, rotationY) {
this.card.style.transform = `translateY(-10px) perspective(${this.perspective}px) rotateX(${rotationX}deg) rotateY(${rotationY}deg) scale(1.05)`;
}
reset(){
this.card.style.transform = `rotateX(0deg) rotateY(0deg) scale(1)`;
}
}

View File

@@ -21,6 +21,47 @@ hr {
animation: blink 800ms infinite; animation: blink 800ms infinite;
} }
.card-list
{
display: flex;
flex-direction: row;
justify-content: start;
gap: 15px;
min-width: 375px;
height: 75%;
overflow: scroll;
padding: 0 20px 0 20px;
}
.card {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
height: 350px;
width: 275px;
background: white;
border-radius: 16px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
padding: 15px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
will-change: transform;
}
.card:hover {
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
}
.card p
{
opacity: 0.65;
}
@keyframes blink { @keyframes blink {
from { opacity: 0; } from { opacity: 0; }
to { opacity: 1; } to { opacity: 1; }

View File

@@ -1,75 +1,9 @@
#projects .content { #projects {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: start;
width: 75%;
}
#projects .content div hr {
margin : 25px 0 25px 0;
}
.project-list, .links {
display: flex;
flex-direction: row;
gap : 1rem;
margin-bottom: 2rem;
}
.project-list img {
width: 215px;
border : solid 1px black;
border-radius: 15px;
transition: transform 0.2s ease-in-out;
}
.project-list img:hover {
transform: scale(1.1);
}
.links {
display: flex;
height: 100%;
font-size: 1.3rem;
}
.links ul {
display: flex;
flex-direction: column;
gap: 40px;
padding : 0;
margin: 0;
}
.links ul li {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: center;
padding: 0.5rem 1rem; width: 95%;
border-radius: 10px; height: 95%;
transition: background 0.3s ease;
}
.links ul li:hover {
background: rgba(0, 0, 0, 0.1);
}
.links ul li::before {
content: ">";
margin-right: 1rem;
}
.links ul li:hover::before {
animation: blink 1s step-start infinite;
}
@keyframes blink {
50% {
opacity: 0;
}
} }

View File

@@ -0,0 +1,76 @@
#projects .content {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: start;
width: 75%;
}
#projects .content div hr {
margin : 25px 0 25px 0;
}
.project-list, .links {
display: flex;
flex-direction: row;
gap : 1rem;
margin-bottom: 2rem;
}
.project-list img {
width: 215px;
border : solid 1px black;
border-radius: 15px;
transition: transform 0.2s ease-in-out;
}
.project-list img:hover {
transform: scale(1.1);
}
.links {
display: flex;
height: 100%;
font-size: 1.3rem;
}
.links ul {
display: flex;
flex-direction: column;
gap: 40px;
padding : 0;
margin: 0;
}
.links ul li {
display: flex;
flex-direction: row;
align-items: center;
padding: 0.5rem 1rem;
border-radius: 10px;
transition: background 0.3s ease;
}
.links ul li:hover {
background: rgba(0, 0, 0, 0.1);
}
.links ul li::before {
content: ">";
margin-right: 1rem;
}
.links ul li:hover::before {
animation: blink 1s step-start infinite;
}
@keyframes blink {
50% {
opacity: 0;
}
}

View File

@@ -1,5 +1,5 @@
:root { :root {
--primary-color: #3dae15;
} }
::-webkit-scrollbar { ::-webkit-scrollbar {
@@ -13,8 +13,8 @@
} }
html, body { html, body {
height: 100vh; height: 100dvh;
width: 100vw; width: 100dvw;
} }
html, body, main, section, section div, footer { html, body, main, section, section div, footer {
@@ -58,3 +58,7 @@ ul li{
ul li a { ul li a {
text-decoration: none; text-decoration: none;
} }
.accentuated {
color: var(--primary-color);
}