.seugagogo-bird-section
position: relative !important;
min-height: 420px;
overflow: hidden !important;
isolation: isolate;
/* Make the Elementor HTML widget cover the section */
.seugagogo-bird-section .elementor-widget-html:has(.seugagogo-bird-animation)
position: absolute !important;
inset: 0 !important;
width: 100% !important;
height: 100% !important;
z-index: 20 !important;
pointer-events: none;
.seugagogo-bird-section
.elementor-widget-html:has(.seugagogo-bird-animation)
> .elementor-widget-container
position: absolute !important;
inset: 0 !important;
width: 100% !important;
height: 100% !important;
.seugagogo-bird-animation
position: absolute;
inset: 0;
width: 100%;
height: 100%;
overflow: visible;
pointer-events: none;
.seugagogo-flight-svg
position: absolute;
inset: 0;
display: block;
width: 100%;
height: 100%;
overflow: visible;
/* Dotted curved path */
.seugagogo-flight-line
fill: none;
stroke: #1aa28f;
stroke-width: 4;
stroke-linecap: round;
stroke-dasharray: 10 17;
opacity: 0.42;
vector-effect: non-scaling-stroke;
/* Moving bird */
.seugagogo-flying-bird
position: absolute !important;
left: 0;
top: 0;
display: block !important;
width: 120px !important;
max-width: none !important;
height: auto !important;
opacity: 1 !important;
visibility: visible !important;
z-index: 30;
pointer-events: none;
transform: translate(-50%, -50%);
transform-origin: center;
will-change: left, top, transform;
body
overflow-x: clip;
@media (max-width: 767px) {
.seugagogo-bird-section
min-height: 340px;
.seugagogo-flying-bird
width: 75px !important;
.seugagogo-flight-line
stroke-width: 3;
stroke-dasharray: 8 14;
}
@media (prefers-reduced-motion: reduce) {
.seugagogo-flying-bird
display: none !important;
}
document.addEventListener('DOMContentLoaded', function () {
const animations = document.querySelectorAll(
'.seugagogo-bird-animation'
);
animations.forEach(function (animation) {
const section = animation.closest('.seugagogo-bird-section');
const svg = animation.querySelector('.seugagogo-flight-svg');
const path = animation.querySelector('.seugagogo-motion-path');
const bird = animation.querySelector('.seugagogo-flying-bird');
if (!section || !svg || !path || !bird)
return;
let currentProgress = 0;
let targetProgress = 0;
let animationRunning = false;
function calculateTargetProgress()
const sectionRect = section.getBoundingClientRect();
const viewportHeight = window.innerHeight;
const totalDistance =
sectionRect.height + viewportHeight;
const travelled =
viewportHeight - sectionRect.top;
targetProgress = travelled / totalDistance;
targetProgress = Math.max(
0,
Math.min(1, targetProgress)
);
function positionBird(progress) {
const pathLength = path.getTotalLength();
const point = path.getPointAtLength(
pathLength * progress
);
const nextPoint = path.getPointAtLength(
Math.min(
pathLength,
pathLength * progress + 3
)
);
const angle = Math.atan2(
nextPoint.y - point.y,
nextPoint.x - point.x
) * 180 / Math.PI;
const viewBox = svg.viewBox.baseVal;
const scaleX = svg.clientWidth / viewBox.width;
const scaleY = svg.clientHeight / viewBox.height;
bird.style.left =
`$
point.x * scaleXpx`;
bird.style.top =
`$
point.y * scaleYpx`;
bird.style.transform =
`translate(-50%, -50%) rotate($
angledeg)`;
}
function animateBird() {
/*
* Lower number means slower movement.
* 0.025 gives a gentle delayed glide.
*/
const smoothing = 0.025;
currentProgress +=
(targetProgress - currentProgress) * smoothing;
positionBird(currentProgress);
if (
Math.abs(
targetProgress - currentProgress
) > 0.0001
)
requestAnimationFrame(animateBird);
else
currentProgress = targetProgress;
positionBird(currentProgress);
animationRunning = false;
}
function updateBird() {
calculateTargetProgress();
if (!animationRunning)
animationRunning = true;
requestAnimationFrame(animateBird);
}
window.addEventListener(
'scroll',
updateBird,
passive: true
);
window.addEventListener(
'resize',
updateBird
);
calculateTargetProgress();
currentProgress = targetProgress;
positionBird(currentProgress);
});
});