You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
nao-web-ui/butterfly-wing-test.html

275 lines
9.4 KiB

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Butterfly Wing Flapping Test</title>
<style>
body {
margin: 0;
padding: 50px;
background: linear-gradient(135deg, #e3f2fd 0%, #f3e5f5 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: Arial, sans-serif;
}
.container {
text-align: center;
}
.butterfly {
width: 200px;
height: 160px;
position: relative;
margin: 50px auto;
}
/* Simple synchronized wing flapping - like reference images */
@keyframes wingFlapLeft {
0% {
transform: rotateZ(-20deg);
}
50% {
transform: rotateZ(-70deg);
}
100% {
transform: rotateZ(-20deg);
}
}
@keyframes wingFlapRight {
0% {
transform: rotateZ(20deg);
}
50% {
transform: rotateZ(70deg);
}
100% {
transform: rotateZ(20deg);
}
}
.wing-left {
transform-origin: 70px 80px; /* Where wing attaches to body */
animation: wingFlapLeft 0.6s ease-in-out infinite;
}
.wing-right {
transform-origin: 130px 80px; /* Where wing attaches to body */
animation: wingFlapRight 0.6s ease-in-out infinite;
}
/* Test different speeds */
.butterfly.slow .wing-left,
.butterfly.slow .wing-right {
animation-duration: 1.2s;
}
.butterfly.fast .wing-left,
.butterfly.fast .wing-right {
animation-duration: 0.3s;
}
.controls {
margin: 20px 0;
}
button {
margin: 0 10px;
padding: 10px 20px;
border: 2px solid #1976d2;
background: white;
color: #1976d2;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
}
button.active {
background: #1976d2;
color: white;
}
h1 {
color: #333;
margin-bottom: 10px;
}
p {
color: #666;
margin: 5px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>🦋 Butterfly Wing Flapping Test</h1>
<p>Testing different wing flapping animations with 3D rotation</p>
<div class="butterfly" id="butterfly">
<svg viewBox="0 0 200 160" width="200" height="160">
<!-- Wing gradients -->
<defs>
<radialGradient id="morphoBlue" cx="50%" cy="30%" r="70%">
<stop offset="0%" style="stop-color: #00D4FF; stop-opacity: 1" />
<stop offset="40%" style="stop-color: #0099CC; stop-opacity: 1" />
<stop offset="80%" style="stop-color: #003366; stop-opacity: 1" />
<stop offset="100%" style="stop-color: #001122; stop-opacity: 1" />
</radialGradient>
<radialGradient id="morphoBlueSecondary" cx="50%" cy="30%" r="70%">
<stop offset="0%" style="stop-color: #33AAFF; stop-opacity: 1" />
<stop offset="40%" style="stop-color: #0077AA; stop-opacity: 1" />
<stop offset="80%" style="stop-color: #002244; stop-opacity: 1" />
<stop offset="100%" style="stop-color: #000D1A; stop-opacity: 1" />
</radialGradient>
<linearGradient id="bodyGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color: #2D1B1B; stop-opacity: 1" />
<stop offset="50%" style="stop-color: #1A0F0F; stop-opacity: 1" />
<stop offset="100%" style="stop-color: #0D0505; stop-opacity: 1" />
</linearGradient>
<filter id="glow">
<feGaussianBlur stdDeviation="2" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Left wings -->
<g class="wing-left">
<!-- Left upper wing -->
<path
d="M70 80 Q30 50 15 30 Q10 20 15 15 Q30 10 50 25 Q64 40 70 60 Z"
fill="url(#morphoBlue)"
stroke="#001122"
stroke-width="1"
filter="url(#glow)"
/>
<!-- Left lower wing -->
<path
d="M70 80 Q40 100 25 120 Q15 130 20 135 Q30 145 50 125 Q64 105 70 90 Z"
fill="url(#morphoBlueSecondary)"
stroke="#001122"
stroke-width="1"
filter="url(#glow)"
/>
<!-- Wing spots -->
<circle cx="45" cy="40" r="4" fill="#00AAFF" opacity="0.7" />
<circle cx="35" cy="55" r="3" fill="#33BBFF" opacity="0.6" />
<circle cx="50" cy="110" r="3.5" fill="#00AAFF" opacity="0.7" />
</g>
<!-- Right wings -->
<g class="wing-right">
<!-- Right upper wing -->
<path
d="M130 80 Q170 50 185 30 Q190 20 185 15 Q170 10 150 25 Q136 40 130 60 Z"
fill="url(#morphoBlue)"
stroke="#001122"
stroke-width="1"
filter="url(#glow)"
/>
<!-- Right lower wing -->
<path
d="M130 80 Q160 100 175 120 Q185 130 180 135 Q170 145 150 125 Q136 105 130 90 Z"
fill="url(#morphoBlueSecondary)"
stroke="#001122"
stroke-width="1"
filter="url(#glow)"
/>
<!-- Wing spots -->
<circle cx="155" cy="40" r="4" fill="#00AAFF" opacity="0.7" />
<circle cx="165" cy="55" r="3" fill="#33BBFF" opacity="0.6" />
<circle cx="150" cy="110" r="3.5" fill="#00AAFF" opacity="0.7" />
</g>
<!-- Butterfly body -->
<ellipse
cx="100"
cy="80"
rx="6"
ry="50"
fill="url(#bodyGradient)"
stroke="#0D0505"
stroke-width="1"
/>
<!-- Head -->
<circle
cx="100"
cy="40"
r="8"
fill="#2D1B1B"
stroke="#0D0505"
stroke-width="1"
/>
<!-- Antennae -->
<path
d="M95 35 Q90 25 85 15"
stroke="#2D1B1B"
stroke-width="2"
fill="none"
stroke-linecap="round"
/>
<path
d="M105 35 Q110 25 115 15"
stroke="#2D1B1B"
stroke-width="2"
fill="none"
stroke-linecap="round"
/>
<!-- Antennae tips -->
<circle cx="85" cy="15" r="2" fill="#2D1B1B" />
<circle cx="115" cy="15" r="2" fill="#2D1B1B" />
<!-- Eyes -->
<circle cx="93" cy="35" r="2" fill="#000" />
<circle cx="107" cy="35" r="2" fill="#000" />
<circle cx="93" cy="35" r="1" fill="#FFF" opacity="0.6" />
<circle cx="107" cy="35" r="1" fill="#FFF" opacity="0.6" />
</svg>
</div>
<div class="controls">
<p>Wing Flapping Speed:</p>
<button class="active" onclick="setSpeed('normal')">Normal (0.6s)</button>
<button onclick="setSpeed('slow')">Slow (1.2s)</button>
<button onclick="setSpeed('fast')">Fast (0.3s)</button>
</div>
<p>Watch the wings! They should flap up and down with 3D rotation.</p>
</div>
<script>
function setSpeed(speed) {
const butterfly = document.getElementById('butterfly');
const buttons = document.querySelectorAll('button');
// Remove all speed classes
butterfly.classList.remove('slow', 'fast');
buttons.forEach(btn => btn.classList.remove('active'));
// Add new speed class
if (speed !== 'normal') {
butterfly.classList.add(speed);
}
// Mark active button
event.target.classList.add('active');
}
</script>
</body>
</html>