Skip to content

Commit 4fb9737

Browse files
author
Abdul Bari
committed
Add scroll-based morphing: Sphere crystallizes as you explore
INTERACTION UPGRADE: - Sphere gradually morphs into diamond as you scroll toward research cards - Starts morphing 300px before cards come into view - Instant full morph when hovering over any research card - Returns to scroll-based state when leaving cards Technical implementation: - Scroll event listener calculates proximity to .research-grid - Progress mapped linearly from 300px trigger distance - Card hover detection via .research-card querySelector - Initial scroll check on page load for correct state Creates natural connection between visual element and content. User feedback: 'it can turn into a diamond when you hover over the cards!'
1 parent 9b0e8a8 commit 4fb9737

1 file changed

Lines changed: 48 additions & 11 deletions

File tree

docs/three-sphere-morph.js

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ class MorphingSphere {
5151
this.init();
5252
this.animate();
5353
this.setupEventListeners();
54+
55+
// Check initial scroll position
56+
setTimeout(() => this.handleScroll(), 100);
5457
}
5558

5659
init() {
@@ -269,19 +272,13 @@ class MorphingSphere {
269272
this.container.addEventListener('mouseleave', () => {
270273
this.isHovered = false;
271274
this.targetScale = 1;
272-
273-
// Return to sphere when mouse leaves
274-
if (this.isMorphed) {
275-
this.isMorphed = false;
276-
this.targetMorphProgress = 0;
277-
}
278275
});
279276

280-
// Click to toggle morph
281-
this.container.addEventListener('click', () => {
282-
this.isMorphed = !this.isMorphed;
283-
this.targetMorphProgress = this.isMorphed ? 1 : 0;
284-
});
277+
// Scroll-based morphing
278+
window.addEventListener('scroll', () => this.handleScroll(), { passive: true });
279+
280+
// Research card hover detection
281+
this.setupCardHoverDetection();
285282

286283
// Resize
287284
window.addEventListener('resize', () => this.onResize());
@@ -315,6 +312,46 @@ class MorphingSphere {
315312
this.targetRotation.y = this.mouse.x * 0.3;
316313
}
317314

315+
handleScroll() {
316+
const researchGrid = document.querySelector('.research-grid');
317+
if (!researchGrid) return;
318+
319+
const rect = researchGrid.getBoundingClientRect();
320+
const windowHeight = window.innerHeight;
321+
322+
// Calculate how close the research grid is to viewport
323+
// Morph starts when grid is 300px below viewport, completes when grid is in view
324+
const triggerDistance = 300;
325+
const distanceFromView = rect.top - windowHeight;
326+
327+
if (distanceFromView < triggerDistance) {
328+
// Map distance to morph progress (0 to 1)
329+
const progress = Math.max(0, Math.min(1, 1 - (distanceFromView / triggerDistance)));
330+
this.targetMorphProgress = progress;
331+
} else {
332+
this.targetMorphProgress = 0;
333+
}
334+
}
335+
336+
setupCardHoverDetection() {
337+
// Wait for DOM to be ready, then attach hover listeners to research cards
338+
setTimeout(() => {
339+
const cards = document.querySelectorAll('.research-card');
340+
341+
cards.forEach(card => {
342+
card.addEventListener('mouseenter', () => {
343+
// Full morph when hovering over any card
344+
this.targetMorphProgress = 1;
345+
});
346+
347+
card.addEventListener('mouseleave', () => {
348+
// Return to scroll-based morph
349+
this.handleScroll();
350+
});
351+
});
352+
}, 100);
353+
}
354+
318355
updateRotation() {
319356
// Smooth interpolation towards target rotation
320357
this.currentRotation.x += (this.targetRotation.x - this.currentRotation.x) * 0.05;

0 commit comments

Comments
 (0)