@manufosela/animation-solarsystem
SVG animated solar system web component built with Lit 3
Demo code (CodePen-ready HTML, CSS, JS)
HTML (html)
<div class="demo-container">
<h1>Animation Solar System Demo</h1>
<div class="component-wrapper">
<animation-solarsystem id="solarSystem"></animation-solarsystem>
</div>
<div class="controls">
<div class="control-group">
<label>Speed: <span id="speedValue">1</span>x</label>
<input type="range" id="speedSlider" min="0.1" max="5" step="0.1" value="1" />
</div>
<div class="control-group">
<label>Scale: <span id="scaleValue">1</span>x</label>
<input type="range" id="scaleSlider" min="0.3" max="1.5" step="0.1" value="1" />
</div>
<div class="control-group">
<label>Show Labels</label>
<input type="checkbox" id="labelsToggle" checked />
</div>
<div class="control-group">
<label>Show Orbits</label>
<input type="checkbox" id="orbitsToggle" checked />
</div>
<button id="pauseBtn">Pause</button>
<button id="resetBtn">Reset</button>
</div>
<div class="event-log">
<h3>Event Log (click a planet)</h3>
<div id="logContent"></div>
</div>
<h2 style="text-align: center; margin: 3rem 0 1rem">Themed Example</h2>
<div class="component-wrapper">
<animation-solarsystem class="themed-solar-system" speed="0.5"></animation-solarsystem>
</div>
</div> CSS (css)
:root {
--bg: #0c0f14;
--bg-elevated: #141923;
--bg-panel: #171d28;
--border: #262f3f;
--text: #f4f6fb;
--text-muted: #a7b0c2;
--text-dim: #7d879b;
--accent: #ff8a3d;
--accent-strong: #ff6a00;
--accent-soft: rgba(255, 138, 61, 0.16);
--shadow: 0 20px 50px rgba(5, 8, 14, 0.45);
--radius-lg: 22px;
--radius-md: 14px;
--radius-sm: 10px;
--max-width: 1160px;
}
<script type="module" src="../src/animation-solarsystem.js"></script>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
h1 {
text-align: center;
margin-bottom: 2rem;
font-weight: 300;
letter-spacing: 2px;
}
.demo-container {
max-width: 1200px;
margin: 0 auto;
}
.component-wrapper {
display: flex;
justify-content: center;
margin-bottom: 2rem;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 1rem;
justify-content: center;
margin-bottom: 2rem;
padding: 1.5rem;
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
backdrop-filter: blur(10px);
}
.control-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.control-group label {
font-size: 0.875rem;
opacity: 0.8;
}
button {
padding: 0.75rem 1.5rem;
border: none;
border-radius: 8px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-size: 1rem;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 20px rgba(102, 126, 234, 0.4);
}
button:active {
transform: translateY(0);
}
input[type='range'] {
width: 150px;
accent-color: #667eea;
}
input[type='checkbox'] {
width: 20px;
height: 20px;
accent-color: #667eea;
}
.event-log {
max-width: 600px;
margin: 2rem auto;
padding: 1rem;
background: rgba(0, 0, 0, 0.3);
border-radius: 8px;
font-family: monospace;
font-size: 0.875rem;
max-height: 150px;
overflow-y: auto;
}
.event-log h3 {
margin-bottom: 0.5rem;
font-weight: 500;
}
.event-item {
padding: 0.25rem 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
/* Custom theming example */
.themed-solar-system {
--solarsystem-width: 500px;
--solarsystem-height: 500px;
--solarsystem-background: radial-gradient(ellipse at center, #2d1b4e 0%, #1a0a2e 100%);
--solarsystem-sun-color: #ff6b6b;
--solarsystem-sun-glow: #ff4757;
--solarsystem-orbit-color: rgba(255, 107, 107, 0.3);
--solarsystem-label-color: #ffeaa7;
} JS (js)
const solarSystem = document.getElementById('solarSystem');
const speedSlider = document.getElementById('speedSlider');
const scaleSlider = document.getElementById('scaleSlider');
const labelsToggle = document.getElementById('labelsToggle');
const orbitsToggle = document.getElementById('orbitsToggle');
const pauseBtn = document.getElementById('pauseBtn');
const resetBtn = document.getElementById('resetBtn');
const logContent = document.getElementById('logContent');
speedSlider.addEventListener('input', (e) => {
const value = parseFloat(e.target.value);
solarSystem.speed = value;
document.getElementById('speedValue').textContent = value.toFixed(1);
});
scaleSlider.addEventListener('input', (e) => {
const value = parseFloat(e.target.value);
solarSystem.scale = value;
document.getElementById('scaleValue').textContent = value.toFixed(1);
});
labelsToggle.addEventListener('change', (e) => {
solarSystem.showLabels = e.target.checked;
});
orbitsToggle.addEventListener('change', (e) => {
solarSystem.showOrbits = e.target.checked;
});
pauseBtn.addEventListener('click', () => {
solarSystem.toggle();
pauseBtn.textContent = solarSystem.paused ? 'Resume' : 'Pause';
});
resetBtn.addEventListener('click', () => {
solarSystem.reset();
});
solarSystem.addEventListener('planet-click', (e) => {
const planet = e.detail.planet;
const logItem = document.createElement('div');
logItem.className = 'event-item';
logItem.textContent = `Clicked: ${planet.name} (size: ${planet.size}, orbit: ${planet.orbitRadius}px)`;
logContent.prepend(logItem);
// Keep only last 10 entries
while (logContent.children.length > 10) {
logContent.removeChild(logContent.lastChild);
}
});