<div class="stories-container">
<div class="stories-wrapper">
<div class="stories-progress">
<!-- Прогресс-бары генерируются JavaScript -->
</div>
<div class="stories-content">
<!-- Stories контент -->
</div>
<button class="stories-nav stories-prev">
<svg width="24" height="24" viewBox="0 0 24 24">
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
</svg>
</button>
<button class="stories-nav stories-next">
<svg width="24" height="24" viewBox="0 0 24 24">
<path d="M8.59 7.41L10 6l6 6-6 6-1.41-1.41L13.17 12z"/>
</svg>
</button>
</div>
</div>
<style>
.stories-container {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.stories-wrapper {
position: relative;
width: 100%;
height: 100%;
}
.stories-progress {
position: absolute;
top: 20px;
left: 0;
right: 0;
display: flex;
gap: 4px;
padding: 0 16px;
z-index: 10;
}
.progress-bar {
flex: 1;
height: 2px;
background: rgba(255, 255, 255, 0.3);
border-radius: 2px;
}
.progress-bar-fill {
width: 0;
height: 100%;
background: #fff;
border-radius: 2px;
transition: width 0.1s linear;
}
.stories-content {
position: relative;
width: 100%;
height: 100%;
display: flex;
transition: transform 0.3s ease;
}
.story-item {
min-width: 100%;
height: 100%;
background-size: cover;
background-position: center;
}
.stories-nav {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255, 255, 255, 0.1);
border: none;
width: 40px;
height: 40px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.3s;
z-index: 10;
}
.stories-nav svg {
fill: #fff;
}
.stories-prev {
left: 16px;
}
.stories-next {
right: 16px;
}
.stories-nav:hover {
background: rgba(255, 255, 255, 0.2);
}
@media (max-width: 768px) {
.stories-nav {
display: none;
}
}
</style>
<script>
class Stories {
constructor(container) {
this.container = container;
this.wrapper = container.querySelector('.stories-wrapper');
this.content = container.querySelector('.stories-content');
this.progressContainer = container.querySelector('.stories-progress');
this.stories = [
{ background: 'https://static.tildacdn.com/5335cb84-d1f6-4fe4-ad8d-89c9565dc051/photo14533964506733fe83d2db2c4.jpeg', duration: 5000 },
{ background: 'https://static.tildacdn.com/d035c716-f5b0-424c-8b24-443d44ac1832/photo14539043002350f2f60b15b5d1.jpeg', duration: 5000 },
{ background: 'https://static.tildacdn.com/4c650eff-0409-417d-a8d0-5922c110ded3/photo14539292030625b1b9cb4cb941.jpeg', duration: 5000 },
// Добавьте свои истории здесь
];
this.currentStory = 0;
this.init();
}
init() {
this.createStories();
this.createProgressBars();
this.bindEvents();
this.play();
}
createStories() {
this.stories.forEach(story => {
const div = document.createElement('div');
div.className = 'story-item';
div.style.backgroundImage = `url(${story.background})`;
this.content.appendChild(div);
});
}
createProgressBars() {
this.stories.forEach(() => {
const bar = document.createElement('div');
bar.className = 'progress-bar';
const fill = document.createElement('div');
fill.className = 'progress-bar-fill';
bar.appendChild(fill);
this.progressContainer.appendChild(bar);
});
}
bindEvents() {
this.container.querySelector('.stories-prev').addEventListener('click', () => this.prev());
this.container.querySelector('.stories-next').addEventListener('click', () => this.next());
this.container.addEventListener('mouseenter', () => this.pause());
this.container.addEventListener('mouseleave', () => {
this.play();
});
let touchStartX = 0;
this.container.addEventListener('touchstart', e => {
touchStartX = e.touches[0].clientX;
this.pause();
});
this.container.addEventListener('touchend', e => {
const touchEndX = e.changedTouches[0].clientX;
const diff = touchStartX - touchEndX;
if (Math.abs(diff) > 50) {
if (diff > 0) this.next();
else this.prev();
}
this.play();
});
}
play() {
const currentStoryData = this.stories[this.currentStory];
const progressBar = this.progressContainer.children[this.currentStory].querySelector('.progress-bar-fill');
let startTime = null;
const animate = timestamp => {
if (!startTime) startTime = timestamp;
const progress = timestamp - startTime;
const percentage = Math.min(progress / currentStoryData.duration * 100, 100);
progressBar.style.width = `${percentage}%`;
if (progress < currentStoryData.duration) {
this.animationFrame = requestAnimationFrame(animate);
} else {
this.next();
}
};
this.animationFrame = requestAnimationFrame(animate);
}
pause() {
cancelAnimationFrame(this.animationFrame);
}
next() {
this.currentStory++;
if (this.currentStory >= this.stories.length) {
this.currentStory = 0;
}
this.updateStory();
}
prev() {
this.currentStory--;
if (this.currentStory < 0) {
this.currentStory = this.stories.length - 1;
}
this.updateStory();
}
updateStory() {
this.content.style.transform = `translateX(-${this.currentStory * 100}%)`;
this.progressContainer.querySelectorAll('.progress-bar-fill').forEach((fill, index) => {
fill.style.width = index < this.currentStory ? '100%' : '0%';
});
cancelAnimationFrame(this.animationFrame);
this.play();
}
}
// Инициализация
document.addEventListener('DOMContentLoaded', () => {
const storiesContainer = document.querySelector('.stories-container');
new Stories(storiesContainer);
});
</script>