All Prompts
All Prompts

scrollsectionparticlesbackgroundtailwindinteractiveanimationlanding page
Particles Background with Full-Page Scroll Navigation
Интерактивный фон с частицами и навигацией по разделам. Идеально для лендингов, портфолио и презентаций. Адаптивный дизайн с Tailwind CSS.
Prompt
<div id="particles-js" class="absolute inset-0 -z-10">
<script src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Initialize ParticlesJS
particlesJS('particles-js', {
particles: {
number: { value: 80, density: { enable: true, value_area: 800 } },
color: { value: "#ffffff" },
shape: { type: "circle" },
opacity: { value: 0.5, random: false },
size: { value: 3, random: true },
line_linked: { enable: true, distance: 150, color: "#ffffff", opacity: 0.4, width: 1 },
move: { enable: true, speed: 6, direction: "none", random: false, straight: false, out_mode: "out", bounce: false }
},
interactivity: {
detect_on: "canvas",
events: { onhover: { enable: true, mode: "repulse" }, onclick: { enable: true, mode: "push" }, resize: true },
modes: { grab: { distance: 400, line_linked: { opacity: 1 } }, bubble: { distance: 400, size: 40, duration: 2, opacity: 8, speed: 3 }, repulse: { distance: 200, duration: 0.4 }, push: { particles_nb: 4 }, remove: { particles_nb: 2 } }
},
retina_detect: true
});
const sections = document.querySelectorAll('.section');
const dots = document.querySelectorAll('.progress-dot');
const magneticElements = document.querySelectorAll('.magnetic');
let currentIndex = 0;
let isScrolling = false;
let touchStartY = 0;
// Initialize
updateActiveDot(currentIndex);
// Magnetic effect
magneticElements.forEach(el => {
el.addEventListener('mousemove', (e) => {
const rect = el.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
el.style.transform = `translate(${x * 0.1}px, ${y * 0.1}px)`;
});
el.addEventListener('mouseleave', () => {
el.style.transform = 'translate(0px, 0px)';
});
});
// Scroll event
window.addEventListener('wheel', (e) => {
if (isScrolling) return;
isScrolling = true;
if (e.deltaY > 0) {
if (currentIndex < sections.length - 1) {
currentIndex++;
changeSection(currentIndex);
}
} else {
if (currentIndex > 0) {
currentIndex--;
changeSection(currentIndex);
}
}
setTimeout(() => {
isScrolling = false;
}, 1200);
});
// Touch events
document.addEventListener('touchstart', (e) => {
touchStartY = e.touches[0].clientY;
});
document.addEventListener('touchend', (e) => {
if (isScrolling) return;
const touchEndY = e.changedTouches[0].clientY;
const diff = touchStartY - touchEndY;
isScrolling = true;
if (diff > 50) {
if (currentIndex < sections.length - 1) {
currentIndex++;
changeSection(currentIndex);
}
} else if (diff < -50) {
if (currentIndex > 0) {
currentIndex--;
changeSection(currentIndex);
}
}
setTimeout(() => {
isScrolling = false;
}, 1200);
});
// Click on dots
dots.forEach(dot => {
dot.addEventListener('click', () => {
const index = parseInt(dot.getAttribute('data-index'));
currentIndex = index;
changeSection(currentIndex);
});
});
function changeSection(index) {
sections.forEach(section => {
section.classList.remove('active');
});
sections[index].classList.add('active');
updateActiveDot(index);
const reveals = sections[index].querySelectorAll('.reveal');
reveals.forEach((el, i) => {
setTimeout(() => {
el.classList.add('active');
}, i * 150);
});
sections.forEach((section, i) => {
if (i !== index) {
const otherReveals = section.querySelectorAll('.reveal');
otherReveals.forEach(el => {
el.classList.remove('active');
});
}
});
}
function updateActiveDot(index) {
dots.forEach(dot => {
dot.classList.remove('active');
});
dots[index].classList.add('active');
}
});
</script>
</div>