Add animated menu cards
This commit is contained in:
@@ -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
10
html/projects.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
48
html/scripts/CardTilter.js
Normal file
48
html/scripts/CardTilter.js
Normal 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)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
76
html/styles/projects.css.bak
Normal file
76
html/styles/projects.css.bak
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user