diff --git a/css/global.css b/css/global.css index c5012d5..f0afce1 100644 --- a/css/global.css +++ b/css/global.css @@ -75,6 +75,63 @@ body{ } } + .write { + overflow: hidden; + border-right: 2px solid transparent; + width: auto; + padding: 10px 30px; + box-sizing: border-box; + display: inline-block; + max-width: 100%; + word-wrap: break-word; + position: relative; + } + + .write::after { + content: "|"; + position: absolute; + animation: blink-carets 1s infinite; + color: #e3e3e3; + } + +.typing { + display: inline-block; + border-right: 2px solid transparent; +} + +.typing-effect { + animation: typing 1s steps(20, end), blink-caret 0.5s step-end infinite; +} + +@keyframes typing { + from { + width: 0; + } + to { + width: 100%; + } +} + +@keyframes blink-carets { + 0%, + 100% { + opacity: 1; + } /* Fully visible caret at the start and end of the animation */ + 50% { + opacity: 0; + } /* Invisible caret at the middle of the animation */ + } + +@keyframes blink-caret { + from, to { + border-color: transparent; + } + 50% { + border-color: #e3e3e3; + } +} + + .content{ display: none; overflow: hidden; diff --git a/index.html b/index.html index 749399d..8e9a704 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,8 @@ Muhammad Rifzkhy All Fhayed - + + @@ -25,30 +26,30 @@

Hello World!

-

+

Rifzkhy

PORTFOLIO

-
-
+
+

ABOUT ME

-
-
-

MUHAMMAD RIFZKHY ALL FHAYED

-

Hello! I'm Rifzkhy, a Fullstack Developer who is deeply passionate +

+
+

MUHAMMAD RIFZKHY ALL FHAYED

+

Hello! I'm Rifzkhy, a Fullstack Developer who is deeply passionate about 3D modeling, game development, chatbot creation, and digital art. My goal is to create simple and clean solutions that deliver impactful experiences to users.

-
-
-
- +
+
+
- + +
@@ -140,8 +141,8 @@

PROGRAMMING

PROJECT

-
-
+
+
@@ -158,7 +159,7 @@
MatsuriAI
-
+

CERTIFICATE

@@ -184,6 +185,24 @@

AWARD CERTIFICATE

+ +
+
+

SOCIAL MEDIA

+
+ +
+
@@ -200,11 +219,12 @@

AWARD CERTIFICATE

crossorigin="anonymous"> diff --git a/script/global.js b/script/global.js index 881615a..703616a 100644 --- a/script/global.js +++ b/script/global.js @@ -2,74 +2,89 @@ document.addEventListener("contextmenu", (event) => { event.preventDefault(); }); -const texts = ["I'm Rifzkhy", "I'm Programmer", "I'm Desainer"]; +const texts = ["I'm Rifzkhy", "I'm Programmer", "I'm Designer"]; -const typingElement = document.querySelector(".typing"); -let textIndex = 0; +const typingElements = document.querySelectorAll(".typing"); -function type() { +function type(element, text) { let i = 0; - const text = texts[textIndex]; + const typingInterval = setInterval(() => { if (i < text.length) { - typingElement.textContent += text.charAt(i); + element.textContent += text.charAt(i); i++; } else { clearInterval(typingInterval); - setTimeout(erase, 1000); // Wait for a moment before erasing + setTimeout(() => erase(element), 1000); } - }, 200); // Adjust the typing speed by changing the interval (e.g., 50 for faster typing). + }, 200); } -function erase() { +function erase(element) { + const text = element.textContent; + const typingInterval = setInterval(() => { - if (typingElement.textContent.length > 0) { - typingElement.textContent = typingElement.textContent.slice(0, -1); + if (element.textContent.length > 0) { + element.textContent = element.textContent.slice(0, -1); } else { clearInterval(typingInterval); - textIndex = (textIndex + 1) % texts.length; // Move to the next text - setTimeout(type, 500); // Wait for a moment before typing the next text + setTimeout(() => { + textIndex = (textIndex + 1) % texts.length; + type(element, texts[textIndex]); + }, 500); } - }, 50); // Adjust the erasing speed if needed + }, 50); } -window.addEventListener("load", () => { - $(window).on("load", function () { - $("html, body").animate({ scrollTop: 0 }); - $(".loader").fadeOut(1000); - $(".content").fadeIn(1000); - setTimeout(type, 1000); +function checkInView() { + typingElements.forEach((element) => { + const rect = element.getBoundingClientRect(); + if (rect.top >= 0 && rect.bottom <= window.innerHeight) { + // Element is in view, start typing effect + if (element.textContent === "") { + textIndex = (textIndex + 1) % texts.length; + type(element, texts[textIndex]); + } + } else { + // Element is out of view, reset effect + element.textContent = ""; + } }); -}); +} + +// Check if elements are in view when the page loads +checkInView(); + +// Check if elements are in view when the user scrolls +window.addEventListener("scroll", checkInView); +//! Scroll effect const scrollElements = document.querySelectorAll(".js-scroll"); -const elementInView = (el, dividend = 1) => { +function elementInView(el, dividend = 1) { const elementTop = el.getBoundingClientRect().top; - return ( elementTop <= (window.innerHeight || document.documentElement.clientHeight) / dividend ); -}; +} -const elementOutofView = (el) => { +function elementOutofView(el) { const elementTop = el.getBoundingClientRect().top; - return ( elementTop > (window.innerHeight || document.documentElement.clientHeight) ); -}; +} -const displayScrollElement = (element) => { +function displayScrollElement(element) { element.classList.add("scrolled"); -}; +} -const hideScrollElement = (element) => { +function hideScrollElement(element) { element.classList.remove("scrolled"); -}; +} -const handleScrollAnimation = () => { +function handleScrollAnimation() { scrollElements.forEach((el) => { if (elementInView(el, 1.25)) { displayScrollElement(el); @@ -77,8 +92,44 @@ const handleScrollAnimation = () => { hideScrollElement(el); } }); -}; +} -window.addEventListener("scroll", () => { - handleScrollAnimation(); -}); +// Check if elements are in view when the page loads +handleScrollAnimation(); + +// Check if elements are in view when the user scrolls +window.addEventListener("scroll", handleScrollAnimation); + +//! Writing effect +const elements = document.querySelectorAll(".write"); + +function type(element) { + const text = element.textContent; + element.textContent = ""; + + let i = 0; + + function typeCharacter() { + if (i < text.length) { + element.textContent += text.charAt(i); + i++; + setTimeout(typeCharacter, 200); + } + } + + function checkInView() { + const rect = element.getBoundingClientRect(); + if (rect.top >= 0 && rect.bottom <= window.innerHeight) { + // Element is in view, start typing effect + typeCharacter(); + } + } + + // Check if element is in view when the page loads + checkInView(); + + // Check if element is in view when the user scrolls + window.addEventListener("scroll", checkInView); +} + +elements.forEach(type); diff --git a/src/carousel/test.png b/src/carousel/test.png new file mode 100644 index 0000000..ae6ab7f Binary files /dev/null and b/src/carousel/test.png differ diff --git a/src/icon/paintnet.webp b/src/icon/paintnet.webp index 473fadb..9c0d826 100644 Binary files a/src/icon/paintnet.webp and b/src/icon/paintnet.webp differ diff --git a/test/index.html b/test/index.html index 42183d6..6a17515 100644 --- a/test/index.html +++ b/test/index.html @@ -4,10 +4,66 @@ Typing Effect - + -
- +

+ Hello! I'm Rifzkhy, a Fullstack Developer who is deeply passionate about + 3D modeling, game development, chatbot creation, and digital art. My goal + is to create simple and clean solutions that deliver impactful experiences + to users. +

+ +