Háttéranimációk
Élő topográfiai vonalak
Élő előnézet – az animáció teljes méretben.
Élő előnézet
HTML · CSS · JS
<div class="we-bg-topographic">
<svg class="we-bg-topographic-svg"
viewBox="0 0 1200 700"
preserveAspectRatio="none"
aria-hidden="true">
<g class="we-topo-lines">
<path d="M-100 120
C120 20 260 210 470 115
S820 40 1300 145" />
<path d="M-120 175
C100 75 280 270 500 165
S850 90 1320 195" />
<path d="M-130 235
C90 125 300 335 530 225
S900 140 1340 250" />
<path d="M-140 300
C80 185 315 400 555 290
S930 200 1350 310" />
<path d="M-150 370
C70 245 330 470 580 355
S960 270 1360 375" />
<path d="M-160 445
C60 315 345 545 605 430
S990 340 1370 450" />
<path d="M-170 525
C45 390 360 625 630 510
S1020 420 1380 530" />
<path d="M-180 610
C30 475 375 710 650 595
S1040 500 1390 615" />
</g>
</svg>
<div class="we-bg-topographic-content">
<span>WEBELEMENTS</span>
<h2>Élő domborzat</h2>
<p>
A háttér szintvonalai lassan változnak,
mintha egy folyamatosan mozgó térképet látnál.
</p>
</div>
</div>
.we-bg-topographic {
position: relative;
width: 100%;
min-height: 420px;
overflow: hidden;
background: #080b11;
display: flex;
align-items: center;
justify-content: center;
isolation: isolate;
}
.we-bg-topographic-svg {
position: absolute;
inset: -8% -6%;
width: 112%;
height: 116%;
overflow: visible;
opacity: .5;
transform: rotate(-3deg) scale(1.04);
pointer-events: none;
}
.we-topo-lines {
fill: none;
stroke: #3f9f63;
stroke-width: 1.2;
stroke-linecap: round;
stroke-dasharray: 900 80;
animation:
weTopoFlow 18s linear infinite,
weTopoMorph 11s ease-in-out infinite alternate;
}
.we-topo-lines path:nth-child(2) {
opacity: .82;
animation-delay: -2s, -1s;
}
.we-topo-lines path:nth-child(3) {
opacity: .7;
animation-delay: -4s, -2s;
}
.we-topo-lines path:nth-child(4) {
opacity: .62;
animation-delay: -6s, -3s;
}
.we-topo-lines path:nth-child(5) {
opacity: .55;
animation-delay: -8s, -4s;
}
.we-topo-lines path:nth-child(6) {
opacity: .48;
animation-delay: -10s, -5s;
}
.we-topo-lines path:nth-child(7) {
opacity: .4;
animation-delay: -12s, -6s;
}
.we-topo-lines path:nth-child(8) {
opacity: .32;
animation-delay: -14s, -7s;
}
@keyframes weTopoFlow {
from {
stroke-dashoffset: 0;
}
to {
stroke-dashoffset: -980;
}
}
@keyframes weTopoMorph {
0% {
transform: translate3d(-8px, 0, 0);
}
50% {
transform: translate3d(8px, -5px, 0);
}
100% {
transform: translate3d(-4px, 7px, 0);
}
}
.we-bg-topographic-content {
position: relative;
z-index: 2;
max-width: 650px;
padding: 48px;
text-align: center;
color: #f4f1e9;
pointer-events: none;
}
.we-bg-topographic-content span {
display: block;
margin-bottom: 16px;
color: #7ac98e;
font-family: Inter, system-ui, sans-serif;
font-size: 10px;
font-weight: 700;
letter-spacing: .2em;
}
.we-bg-topographic-content h2 {
margin: 0 0 14px;
font-family: "Bodoni Moda", Georgia, serif;
font-size: clamp(40px, 7vw, 72px);
font-weight: 500;
line-height: 1;
}
.we-bg-topographic-content p {
margin: 0;
color: rgba(244, 241, 233, .62);
font-family: Inter, system-ui, sans-serif;
font-size: 14px;
line-height: 1.7;
}
document.querySelectorAll(".we-bg-topographic").forEach(background => {
const svg = background.querySelector(
".we-bg-topographic-svg"
);
let targetX = 0;
let targetY = 0;
let currentX = 0;
let currentY = 0;
function animate() {
currentX +=
(targetX - currentX) * .035;
currentY +=
(targetY - currentY) * .035;
svg.style.transform =
`rotate(-3deg) scale(1.04)
translate3d(${currentX}px, ${currentY}px, 0)`;
requestAnimationFrame(animate);
}
background.addEventListener("mousemove", event => {
const rect =
background.getBoundingClientRect();
const x =
(event.clientX - rect.left) / rect.width;
const y =
(event.clientY - rect.top) / rect.height;
targetX =
(x - .5) * 28;
targetY =
(y - .5) * 18;
});
background.addEventListener("mouseleave", () => {
targetX = 0;
targetY = 0;
});
animate();
});