-
Notifications
You must be signed in to change notification settings - Fork 0
Optimize Spline rendering using intersection observer #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: fix/0/optimization-v1
Are you sure you want to change the base?
Optimize Spline rendering using intersection observer #26
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR conditionally renders the Spline animation using the Intersection Observer API and updates the landing page to include an About section, along with adding new asset imports for Knot animations.
- Added the About section to Landing.tsx
- Integrated Intersection Observer-based conditional loading for the Spline animation in UpdatesSection
- Exported the About component and added Knot assets in the assets index
Reviewed Changes
Copilot reviewed 13 out of 15 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
src/pages/Landing.tsx | Added the About section component to the landing page |
src/components/sections/updates.section.tsx | Updated Spline loading to use Intersection Observer for conditional rendering |
src/components/index.ts | Exported the new About component alongside other sections |
src/assets/index.ts | Imported and exported new Knot animation assets |
Files not reviewed (2)
- package.json: Language not supported
- pnpm-lock.yaml: Language not supported
3ecf967
to
34e56bf
Compare
34e56bf
to
dde28aa
Compare
…-1/spline-conditional-loading
Try portals: Courtesy of Claude // SplineComponent.jsx
import React, { useRef, useEffect } from 'react';
import { createPortal } from 'react-dom';
import Spline from '@splinetool/react-spline';
const SplinePortal = ({ splineUrl }) => {
// Reference to the original Spline component
const splineRef = useRef(null);
// Create a shared Spline instance that will be rendered once
const SplineInstance = (
<div className="spline-instance" ref={splineRef}>
<Spline scene={splineUrl} />
</div>
);
return (
<>
{/* Render the original Spline component */}
{SplineInstance}
</>
);
};
// Component that creates portals to display the Spline in multiple locations
const SplinePortals = ({ splineUrl, portalTargetIds }) => {
const [loaded, setLoaded] = React.useState(false);
const containerRef = useRef(null);
useEffect(() => {
// Wait for the original Spline to initialize
setLoaded(true);
}, []);
return (
<div className="spline-container" ref={containerRef}>
{/* Render the original Spline (only once) */}
<div className="original-spline" style={{ position: 'fixed', left: '-9999px' }}>
<SplinePortal splineUrl={splineUrl} />
</div>
{/* Create portals to the target locations */}
{loaded &&
portalTargetIds.map((targetId) => {
const targetElement = document.getElementById(targetId);
if (!targetElement) return null;
// Clone the original Spline DOM node and project it to the target location
return createPortal(
<div className="spline-portal">
{/* This will be a reference to the original Spline content */}
<div
className="portal-content"
ref={(node) => {
if (node && containerRef.current) {
// Use an intersection observer or another method to only show
// the portal content when it's in the viewport
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
node.innerHTML = '';
// Create a reference to the original Spline
const splineContainer = containerRef.current.querySelector('.spline-instance');
if (splineContainer) {
// Use iframe technique to optimize performance
const iframe = document.createElement('iframe');
iframe.style.border = 'none';
iframe.style.width = '100%';
iframe.style.height = '100%';
node.appendChild(iframe);
// Copy the Spline content to iframe
iframe.onload = () => {
const doc = iframe.contentDocument;
doc.body.style.margin = '0';
const splineClone = splineContainer.cloneNode(true);
doc.body.appendChild(splineClone);
};
iframe.src = 'about:blank';
}
}
});
}, { threshold: 0.1 });
observer.observe(node);
}
}}
/>
</div>,
targetElement
);
})}
</div>
);
};
// Usage Example
const App = () => {
const splineUrl = 'https://prod.spline.design/your-scene-id/scene.splinecode';
const portalTargets = ['portal-target-1', 'portal-target-2', 'portal-target-3'];
return (
<div className="app">
<h1>Spline with React Portals</h1>
{/* Main Spline Portal Manager */}
<SplinePortals splineUrl={splineUrl} portalTargetIds={portalTargets} />
{/* Portal Target Areas */}
<div className="content-section">
<h2>Section 1</h2>
<div id="portal-target-1" className="portal-target"></div>
</div>
<div className="content-section">
<h2>Section 2</h2>
<div id="portal-target-2" className="portal-target"></div>
</div>
<div className="content-section">
<h2>Section 3</h2>
<div id="portal-target-3" className="portal-target"></div>
</div>
</div>
);
};
export default App; |
Description
Lazy load Spline backgrounds in sections only when they're in view.
Linked Issues
maybe
Testing
unlikely
Reviewer Checklist
When reviewing this PR, make sure to keep the following in mind:
Author Checklist
Before opening this PR, make sure the PR:
Additionally, make sure that: