Gradual transitions
This commit is contained in:
parent
0ad194041c
commit
d3abf042ad
136
index.php
136
index.php
@ -24,6 +24,12 @@ $nav_links = [
|
|||||||
|
|
||||||
$hardware_info = "Playing the mandolin, mountain biking, 3D printing and tinkering.";
|
$hardware_info = "Playing the mandolin, mountain biking, 3D printing and tinkering.";
|
||||||
|
|
||||||
|
$extra_contact_links = [
|
||||||
|
"LinkedIn" => "https://www.linkedin.com/in/hrdinadavid/",
|
||||||
|
"GitHub" => "https://github.com/dejvino",
|
||||||
|
"StackOverflow" => "https://stackoverflow.com/users/3551523/dejvino",
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CV Data
|
* CV Data
|
||||||
*/
|
*/
|
||||||
@ -103,17 +109,6 @@ $cv_skills = ["PHP", "Go", "Rust", "Docker", "Kubernetes", "PostgreSQL", "Redis"
|
|||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card links">
|
|
||||||
<h2>Navigation</h2>
|
|
||||||
<ul class="link-grid">
|
|
||||||
<?php foreach ($nav_links as $label => $url):
|
|
||||||
$id_attr = ($url === "#") ? 'id="cv-toggle"' : '';
|
|
||||||
?>
|
|
||||||
<li><a href="<?= $url ?>" <?= $id_attr ?>><span><?= $label ?></span></a></li>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="card interests">
|
<section class="card interests">
|
||||||
<h2>Likes</h2>
|
<h2>Likes</h2>
|
||||||
<p><?= $hardware_info ?></p>
|
<p><?= $hardware_info ?></p>
|
||||||
@ -124,9 +119,13 @@ $cv_skills = ["PHP", "Go", "Rust", "Docker", "Kubernetes", "PostgreSQL", "Redis"
|
|||||||
<p class="mono-addr">
|
<p class="mono-addr">
|
||||||
Contact email: <span id="contact-mail">uncovering...</span>
|
Contact email: <span id="contact-mail">uncovering...</span>
|
||||||
</p>
|
</p>
|
||||||
|
<ul class="link-grid cv-only hidden">
|
||||||
|
<?php foreach ($extra_contact_links as $label => $url): ?>
|
||||||
|
<li><a href="<?= $url ?>" target="_blank"><span><?= $label ?></span></a></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- CV Hidden Sections -->
|
|
||||||
<section class="card experience hidden">
|
<section class="card experience hidden">
|
||||||
<h2>Experience</h2>
|
<h2>Experience</h2>
|
||||||
<?php foreach ($cv_experience as $job): ?>
|
<?php foreach ($cv_experience as $job): ?>
|
||||||
@ -165,6 +164,20 @@ $cv_skills = ["PHP", "Go", "Rust", "Docker", "Kubernetes", "PostgreSQL", "Redis"
|
|||||||
</div>
|
</div>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="card links">
|
||||||
|
<h2>Navigation</h2>
|
||||||
|
<ul class="link-grid nav-default">
|
||||||
|
<?php foreach ($nav_links as $label => $url):
|
||||||
|
$id_attr = ($url === "#") ? 'id="cv-toggle"' : '';
|
||||||
|
?>
|
||||||
|
<li><a href="<?= $url ?>" <?= $id_attr ?>><span><?= $label ?></span></a></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
<ul class="link-grid cv-only hidden">
|
||||||
|
<li><a href="#" id="cv-back"><span>GO BACK ~/</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -174,14 +187,103 @@ $cv_skills = ["PHP", "Go", "Rust", "Docker", "Kubernetes", "PostgreSQL", "Redis"
|
|||||||
el.innerHTML = `<a href="mailto:${addr}">${addr}</a>`;
|
el.innerHTML = `<a href="mailto:${addr}">${addr}</a>`;
|
||||||
})('<?= $email_user ?>', 'dejvino', 'cz');
|
})('<?= $email_user ?>', 'dejvino', 'cz');
|
||||||
|
|
||||||
|
const animationDuration = 1000; // Matches CSS animation duration (1s)
|
||||||
|
const staggerDelay = 200; // Delay between each panel unrolling (ms)
|
||||||
|
|
||||||
|
const applyShifting = (el, flashAtEnd = true, delay = animationDuration) => {
|
||||||
|
if (!el) return;
|
||||||
|
const card = el.classList.contains('card') ? el : el.closest('.card');
|
||||||
|
if (card && !card.dataset.isShifting) {
|
||||||
|
card.dataset.isShifting = "true";
|
||||||
|
card.classList.add('shifting');
|
||||||
|
setTimeout(() => {
|
||||||
|
card.classList.remove('shifting', 'reveal', 'fade-out');
|
||||||
|
delete card.dataset.isShifting;
|
||||||
|
|
||||||
|
if (!flashAtEnd) return;
|
||||||
|
|
||||||
|
card.classList.add('flash-glow');
|
||||||
|
setTimeout(() => card.classList.remove('flash-glow'), 600);
|
||||||
|
}, delay);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleCV = (show, updateHash = true) => {
|
||||||
|
const grid = document.querySelector('.bento-grid');
|
||||||
|
|
||||||
|
const cvPanels = [
|
||||||
|
document.querySelector('.experience'),
|
||||||
|
document.querySelector('.skills'),
|
||||||
|
document.querySelector('.education'),
|
||||||
|
...document.querySelectorAll('.cv-only')
|
||||||
|
].filter(el => el);
|
||||||
|
|
||||||
|
const navDefault = document.querySelectorAll('.nav-default');
|
||||||
|
|
||||||
|
if (show) {
|
||||||
|
grid.classList.add('cv-mode');
|
||||||
|
|
||||||
|
// Hide default navigation
|
||||||
|
navDefault.forEach(el => {
|
||||||
|
el.classList.remove('reveal');
|
||||||
|
el.classList.add('fade-out');
|
||||||
|
applyShifting(el, false); // No flash when disappearing
|
||||||
|
setTimeout(() => el.classList.add('hidden'), animationDuration);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Unroll CV panels sequentially (Top -> Bottom)
|
||||||
|
cvPanels.forEach((el, index) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
el.classList.remove('hidden', 'fade-out');
|
||||||
|
el.classList.add('reveal');
|
||||||
|
applyShifting(el, true); // Flash when appearing
|
||||||
|
}, index * staggerDelay);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Roll up CV panels sequentially (Bottom -> Top)
|
||||||
|
[...cvPanels].reverse().forEach((el, index) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
el.classList.remove('reveal');
|
||||||
|
el.classList.add('fade-out');
|
||||||
|
applyShifting(el, false); // No flash when disappearing
|
||||||
|
setTimeout(() => {
|
||||||
|
el.classList.add('hidden');
|
||||||
|
el.classList.remove('fade-out');
|
||||||
|
}, animationDuration);
|
||||||
|
}, index * staggerDelay);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Restore default state after panels have started rolling up
|
||||||
|
setTimeout(() => {
|
||||||
|
grid.classList.remove('cv-mode');
|
||||||
|
navDefault.forEach(el => {
|
||||||
|
el.classList.remove('hidden', 'fade-out');
|
||||||
|
el.classList.add('reveal');
|
||||||
|
applyShifting(el, true); // Flash when navigation returns
|
||||||
|
});
|
||||||
|
}, cvPanels.length * staggerDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateHash) {
|
||||||
|
window.location.hash = show ? 'CV' : '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize state from URL
|
||||||
|
const checkHash = () => toggleCV(window.location.hash === '#CV', false);
|
||||||
|
|
||||||
|
window.addEventListener('load', checkHash);
|
||||||
|
window.addEventListener('hashchange', checkHash);
|
||||||
|
|
||||||
document.getElementById('cv-toggle')?.addEventListener('click', (e) => {
|
document.getElementById('cv-toggle')?.addEventListener('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const hiddenCards = document.querySelectorAll('.card.hidden');
|
toggleCV(true);
|
||||||
hiddenCards.forEach(card => {
|
|
||||||
card.classList.remove('hidden');
|
|
||||||
card.classList.add('reveal');
|
|
||||||
});
|
});
|
||||||
e.currentTarget.parentElement.style.display = 'none';
|
|
||||||
|
document.getElementById('cv-back')?.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
toggleCV(false);
|
||||||
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
93
style.css
93
style.css
@ -19,9 +19,40 @@
|
|||||||
100% { transform: translateX(150%) skewX(-45deg); opacity: 0; }
|
100% { transform: translateX(150%) skewX(-45deg); opacity: 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fade-in-up {
|
@keyframes grow-reveal { /* Slower grow transition */
|
||||||
from { opacity: 0; transform: translateY(20px); }
|
from {
|
||||||
to { opacity: 1; transform: translateY(0); }
|
opacity: 0;
|
||||||
|
max-height: 0;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0.4; /* Faded while unrolling */
|
||||||
|
max-height: 2000px; /* Sufficiently large to contain content */
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shrink-fade-away { /* New animation for shrinking */
|
||||||
|
from {
|
||||||
|
opacity: 0.4;
|
||||||
|
max-height: 2000px;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
max-height: 0;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flash-impact {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
filter: brightness(3) saturate(1.5);
|
||||||
|
box-shadow: 0 0 40px var(--accent-color);
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
}
|
||||||
|
100% { opacity: 1; filter: brightness(1) saturate(1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
* { box-sizing: border-box; }
|
* { box-sizing: border-box; }
|
||||||
@ -84,13 +115,38 @@ body {
|
|||||||
.profile { transform: rotate(0.1deg); }
|
.profile { transform: rotate(0.1deg); }
|
||||||
.about { transform: translate(-4px, 2px) rotate(-0.5deg); }
|
.about { transform: translate(-4px, 2px) rotate(-0.5deg); }
|
||||||
.interests { transform: translate(6px, -2px) rotate(0.4deg); }
|
.interests { transform: translate(6px, -2px) rotate(0.4deg); }
|
||||||
.links { transform: translate(-2px, -4px) rotate(-0.3deg); }
|
.links { transform: translate(-2px, -4px) rotate(-0.3deg); grid-column: span 4; }
|
||||||
.contact { transform: translate(4px, 6px) rotate(0.5deg); }
|
.contact { transform: translate(4px, 6px) rotate(0.5deg); grid-column: span 4; }
|
||||||
|
|
||||||
/* CV sections also shuffled */
|
/* CV sections also shuffled */
|
||||||
.experience { transform: translate(3px, -2px) rotate(-0.2deg); }
|
.experience { transform: translate(3px, -2px) rotate(-0.2deg); }
|
||||||
.skills { transform: translate(-3px, 4px) rotate(0.6deg); }
|
.skills { transform: translate(-3px, 4px) rotate(0.6deg); }
|
||||||
.education { transform: translate(2px, 3px) rotate(-0.4deg); }
|
.education { transform: translate(2px, 3px) rotate(-0.4deg); }
|
||||||
|
|
||||||
|
/* Base states to prevent "re-added to DOM" flashes */
|
||||||
|
.experience, .skills, .education, .cv-only {
|
||||||
|
opacity: 0;
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Solid states when CV is fully locked in */
|
||||||
|
.cv-mode .experience, .cv-mode .skills, .cv-mode .education, .cv-mode .cv-only {
|
||||||
|
opacity: 1;
|
||||||
|
max-height: 2000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cv-mode .nav-default {
|
||||||
|
opacity: 0;
|
||||||
|
max-height: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CV mode layout overrides - ensure full width for key info */
|
||||||
|
.cv-mode .education {
|
||||||
|
grid-column: span 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
@ -108,11 +164,32 @@ body {
|
|||||||
.skills { grid-column: span 1; }
|
.skills { grid-column: span 1; }
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reveal {
|
.reveal {
|
||||||
animation: fade-in-up 0.6s cubic-bezier(0.23, 1, 0.32, 1) forwards;
|
display: block !important;
|
||||||
|
animation: grow-reveal 1s cubic-bezier(0.23, 1, 0.32, 1) forwards;
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-out {
|
||||||
|
/* This class will be applied when content is being hidden */
|
||||||
|
animation: shrink-fade-away 1s cubic-bezier(0.23, 1, 0.32, 1) forwards;
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shifting {
|
||||||
|
filter: blur(2px) grayscale(0.5);
|
||||||
|
z-index: 10;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flash-glow {
|
||||||
|
display: block !important;
|
||||||
|
animation: flash-impact 0.6s ease-out forwards;
|
||||||
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CV Specific Content Styles */
|
/* CV Specific Content Styles */
|
||||||
@ -181,8 +258,6 @@ body {
|
|||||||
|
|
||||||
.about { grid-column: span 2; }
|
.about { grid-column: span 2; }
|
||||||
.interests { grid-column: span 2; }
|
.interests { grid-column: span 2; }
|
||||||
.links { grid-column: span 2; }
|
|
||||||
.contact { grid-column: span 2; }
|
|
||||||
|
|
||||||
.link-grid { list-style: none; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
|
.link-grid { list-style: none; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user