ARKit中3D模型悬浮及点击下落动画实现方法问询
Hey there! Let's walk through building this exact effect—objects floating in an orbit around a room, then falling when clicked. I'll break it down step by step, and answer your question about whether you're limited to pre-animated objects.
Core Concept
This effect relies on two connected animation states:
- A default looping orbit animation that keeps objects floating around the room.
- A triggered fall animation that replaces the orbit when the object is clicked, ending with the object leaving the view (or whatever you want to happen post-fall).
Step 1: Basic HTML Structure
First, set up a container for your "room" and the object(s) that will animate:
<div class="room"> <div class="floating-item"></div> </div>
Step 2: Build the Orbit Animation with CSS
We'll use CSS @keyframes to create a smooth circular orbit around the room's center. This example uses nested transforms to keep the object facing forward while moving in a circle:
.room { position: relative; width: 800px; height: 600px; border: 2px solid #333; overflow: hidden; /* Hide objects that fall outside the room */ } .floating-item { position: absolute; width: 50px; height: 50px; background: #ff6b6b; border-radius: 50%; /* Default orbit animation */ animation: orbit 12s linear infinite; } @keyframes orbit { 0% { /* Start at center, rotate around a point 150px away */ transform: translate(400px, 300px) rotate(0deg) translate(150px, 0) rotate(0deg); } 100% { /* Complete a full 360° orbit */ transform: translate(400px, 300px) rotate(360deg) translate(150px, 0) rotate(-360deg); } }
Step 3: Add Click-to-Fall Interaction
We'll use JavaScript to pause the orbit, capture the object's current position, then trigger the fall animation. First, add the fall animation to your CSS:
.floating-item.falling { animation: fall 2.5s ease-in forwards; /* "forwards" keeps the final state */ } @keyframes fall { 0% { transform: translate(var(--current-x), var(--current-y)); /* Start at current position */ opacity: 1; } 100% { transform: translate(var(--current-x), 650px); /* Fall past the room's bottom */ opacity: 0; } }
Then add the JavaScript to handle clicks:
const floatingItem = document.querySelector('.floating-item'); floatingItem.addEventListener('click', () => { // Pause the orbit animation to freeze the object in place floatingItem.style.animationPlayState = 'paused'; // Capture the object's current position relative to the room const roomRect = document.querySelector('.room').getBoundingClientRect(); const itemRect = floatingItem.getBoundingClientRect(); const currentX = itemRect.left - roomRect.left; const currentY = itemRect.top - roomRect.top; // Save position to CSS variables for the fall animation floatingItem.style.setProperty('--current-x', `${currentX}px`); floatingItem.style.setProperty('--current-y', `${currentY}px`); // Trigger the fall animation floatingItem.classList.add('falling'); // Clean up after the animation ends (optional) floatingItem.addEventListener('animationend', () => { floatingItem.remove(); // Remove the object once it falls }, { once: true }); });
Can You Only Use Pre-Animated Objects?
Absolutely not! You have full flexibility to:
- Dynamically create objects: Generate new floating items on the fly (e.g., every 3 seconds) and assign them the orbit animation.
- Reuse objects: After an object falls, reset its position and reapply the orbit animation to make it float again.
- Customize animations per object: Randomize orbit speed, size, or color for each item to make the scene feel more natural.
Here's a quick example of dynamically creating floating objects:
function createFloatingItem() { const newItem = document.createElement('div'); newItem.classList.add('floating-item'); // Randomize orbit duration for variation newItem.style.animationDuration = `${Math.random() * 6 + 8}s`; // Add to room and bind click event document.querySelector('.room').appendChild(newItem); newItem.addEventListener('click', handleItemClick); } // Reuse the click handler from earlier function handleItemClick(e) { const item = e.target; item.style.animationPlayState = 'paused'; const roomRect = document.querySelector('.room').getBoundingClientRect(); const itemRect = item.getBoundingClientRect(); const currentX = itemRect.left - roomRect.left; const currentY = itemRect.top - roomRect.top; item.style.setProperty('--current-x', `${currentX}px`); item.style.setProperty('--current-y', `${currentY}px`); item.classList.add('falling'); item.addEventListener('animationend', () => item.remove(), { once: true }); } // Spawn a new item every 3 seconds setInterval(createFloatingItem, 3000);
Pro Tip: Use Animation Libraries for Easier Control
If you want to avoid manually parsing positions or handling animation state, libraries like GSAP (GreenSock) simplify this work significantly. They let you control animations with precise timing, reverse animations, and manage complex sequences with less code.
内容的提问来源于stack exchange,提问作者Sachin

