I followed this fantastic article, that demonstrates how to make a simple carousel with the use of two directives and one component in Angular.
The feature set is very limited, and does not include an 'infinite scrolling' mode, which I would like to add.
By 'inifinite scroll' - I mean something like this jQuery equivalent:
var carousel = $('#carousel'),
threshold = 150,
slideWidth = 500,
dragStart,
dragEnd;
$('#next').click(function() {
shiftSlide(-1)
})
$('#prev').click(function() {
shiftSlide(1)
})
carousel.on('mousedown', function() {
if (carousel.hasClass('transition')) return;
dragStart = event.pageX;
$(this).on('mousemove', function() {
dragEnd = event.pageX;
$(this).css('transform', 'translateX(' + dragPos() + 'px)')
})
$(document).on('mouseup', function() {
if (dragPos() > threshold) {
return shiftSlide(1)
}
if (dragPos() < -threshold) {
return shiftSlide(-1)
}
shiftSlide(0);
})
});
function dragPos() {
return dragEnd - dragStart;
}
function shiftSlide(direction) {
if (carousel.hasClass('transition')) return;
dragEnd = dragStart;
$(document).off('mouseup')
carousel.off('mousemove')
.addClass('transition')
.css('transform', 'translateX(' + (direction * slideWidth) + 'px)');
setTimeout(function() {
if (direction === 1) {
$('.slide:first').before($('.slide:last'));
} else if (direction === -1) {
$('.slide:last').after($('.slide:first'));
}
carousel.removeClass('transition')
carousel.css('transform', 'translateX(0px)');
}, 700)
}
$carousel-width: 600px;
$carousel-height: 300px;
body {
background: #333;
color: #fff;
font-size: 22pt;
text-align: center;
font-family: 'Teko';
letter-spacing: 0.15em;
}
body * {
-webkit-user-select: none
}
.wrap {
position: relative;
width: $carousel-width;
height: 300px;
margin: 0 auto;
box-shadow: 7px 7px 5px 0px rgba(0, 0, 0, 0.25);
}
.window {
overflow: hidden;
position: relative;
background: #222;
}
#carousel {
width: 10000px;
position: relative;
top: 0;
left: -450px;
}
.slide {
height: 300px;
width: 500px;
cursor: pointer;
float: left;
display: flex;
flex-direction: column;
justify-content: center;
}
.slide#b1 {
background: #556270
}
.slide#b2 {
background: #4ECDC4
}
.slide#b3 {
background: #9CE462
}
.slide#b4 {
background: #FF6B6B
}
.slide#b5 {
background: #C44D33
}
#prev,
#next {
cursor: pointer;
position: absolute;
bottom: -40px;
font-size: 14pt;
}
#prev {
left: 0
}
#next {
right: 0
}
.transition {
transition: .7s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>INFINITE CAROUSEL</h1>
<div class="wrap">
<div class="window">
<div id="carousel">
<span class="slide" id="b1">SLIDE-1</span>
<span class="slide" id="b2">SLIDE-2</span>
<span class="slide" id="b3">SLIDE-3</span>
<span class="slide" id="b4">SLIDE-4</span>
<span class="slide" id="b5">SLIDE-5</span>
</div>
</div>
<span id="prev">PREV</span>
<span id="next">NEXT</span>
</div>
(the carousel can be infinitely scrolled in each direction whilst keeping the correct order of the slides)
I have tried a number of approaches to add this feature and none have succeeded, what I've tried (and subsequently deleted):
Dynamically adding and removing chunks of slides either side of the currently viewed subset - i.e. if the carousel contained 3 slides I would duplicate them either side of the original `1-2-3 1-2-3, and then add/remove chunks as the user scrolls. This almost worked, the only problem was that Angular got confused when removing chunks and spun the carousel like mad, because it still had a reference to a slide number that no longer existed.
Dynamically adding and removing single slides, similar to the above approach. Same issue.
Straight up duplicating the slides hundreds of times. This works but is obviously horribly un-performant and seems dumb.
Here is a stackblitz showing what I've got so far.