Skip to content

Instantly share code, notes, and snippets.

@HeNy007
Created August 28, 2022 13:25
Show Gist options
  • Save HeNy007/4bf4841fbc940660fb092761b69051b8 to your computer and use it in GitHub Desktop.
Save HeNy007/4bf4841fbc940660fb092761b69051b8 to your computer and use it in GitHub Desktop.
Stories Slider | Pure JS | ForFun :)
<div class="ld">
<div class="inside-wrapper">
<div class="container">
<div class="container-item">
<img src="https://images.unsplash.com/photo-1566558843351-b39b612160ab?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1566910087672-124366fda948?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1567508506534-1be34b162d94?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1566617861495-d7b5effb2528?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1568158951631-e1f33137ad76?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1568701905114-bfb7d259a400?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1567465645848-b765281eca3c?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1568193755668-aae18714a9f1?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1568404665732-c0a884963e7b?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1567759134955-9b1e8c4b5cb0?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1567629230779-ca428a942998?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1566558843351-b39b612160ab?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1566910087672-124366fda948?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1567508506534-1be34b162d94?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1566617861495-d7b5effb2528?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1568158951631-e1f33137ad76?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1568701905114-bfb7d259a400?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1567465645848-b765281eca3c?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1568193755668-aae18714a9f1?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1568404665732-c0a884963e7b?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1567759134955-9b1e8c4b5cb0?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
<div class="container-item">
<img src="https://images.unsplash.com/photo-1567629230779-ca428a942998?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
</div>
</div>
<button class="nav-btn prev"><svg style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#000000" d="M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z" />
</svg></button>
<button class="nav-btn next"><svg style="width:24px;height:24px" viewBox="0 0 24 24">
<path fill="#000000" d="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z" />
</svg></button>
</div>
</div>
function StoriesSlider (config) {
this.containerName = config.container;
this.containerEl = document.querySelector(this.containerName);
this.slides = null;
this.itemOffsetSide = config.itemOffsetSide || 0;
this.itemLeftOffset = config.itemLeftOffset === 'undefined' ? this.itemOffsetSide : config.itemLeftOffset;
this.itemRightOffset = config.itemRightOffset === 'undefined' ? this.itemOffsetSide : config.itemRightOffset;
this.minDragDistance = config.minDragDistance === 'undefined' ? 40 : config.minDragDistance;
this.inertionCoef = config.inertionCoef || 0.92;
this.useSelfController = config.useIsideController
? config.useIsideController
: !isNaN(+config.useIsideController)
? config.useIsideController
: null;
this.dataAttributeName = config.dataAttrName ? config.dataAttrName : 'data-sts';
this.dataAttributeValue = config.dataAttrValue ? config.dataAttrValue : 'stories-slider';
this.slidesWrapper = null;
this.childrenArray = null;
this.referencePoint = 0;
this.isDrag = false;
this.offset = 0;
this.offsetForAnimation = 0;
this.tran = 0;
this.pos = 0;
this.diff = 0.05;
this.diffBetweenContainerAndSlidesWrapper = null;
this.isClickPrevent = false;
this.dir = 1; // -1 --- left, 1 --- right;
this.leftPosition = 0;
this.isBorder = false;
this.isGateOpen = false;
this.canInteract = true;
this.setRAF = this.setRAF.bind(this);
this.moveLeft = this.moveLeft.bind(this);
this.moveRight = this.moveRight.bind(this);
this._watcher = this.deb(this.watcher, this, 1000);
this._updater = this.positionUpdaterForClick.bind(this);
this._ls = function () {};
this._rs = function () {};
this._md = function () {};
this.init();
}
StoriesSlider.prototype.getInteractPossibility = function () {
return this.canInteract;
}
StoriesSlider.prototype.watcher = function () {
this.setDiffBetweenContainerAndSlidesWrapper();
}
StoriesSlider.prototype.positionUpdaterForClick = function (fn) {
if (this.isGateOpen) {
this.offset += this.dir * 5;
fn.call(this);
} else {
return false;
}
}
StoriesSlider.prototype.deb = function (fn, ctx, d) {
var t = true;
return function () {
if(t) {
t = false;
setTimeout(function(){
fn.call(ctx);
t = true;
},d);
}else{
return false;
}
}
}
StoriesSlider.prototype.init = function () {
this.childrenArray = this.leadToArray(this.getSlides());
var wrap = this.createSlidesWrapper();
var sizes = this.getFullSizesOfSliderLine(this.childrenArray);
this.setSizesOnSlidesWrapper(sizes);
this.setSlidesOnSlidesWrapper(wrap, this.childrenArray);
this.setWrapperOnContainer(this.slidesWrapper);
this.setDiffBetweenContainerAndSlidesWrapper();
this.setRAF();
if ( this.useSelfController ) {
this.controller();
}
}
StoriesSlider.prototype.getSlides = function () {
return this.containerEl.children;
}
StoriesSlider.prototype.isChildren = function () {
return this.containerEl.childNodes.length !== 0;
}
StoriesSlider.prototype.leadToArray = function (slides) {
return Array.prototype.slice.call(slides);
}
StoriesSlider.prototype.getContainerPaddings = function () {
var _styles = this.containerEl.currentStyle || window.getComputedStyle(this.containerEl);
return {
pl: _styles['padding-left'],
pt: _styles['padding-top'],
pr: _styles['padding-right'],
pb: _styles['padding-bottom']
}
}
StoriesSlider.prototype.getFullSizesOfSliderLine = function (slides) {
var sizes = {w: 0,h: 0};
var pad = this.getContainerPaddings();
var _pl, _pr;
for (var i = 0, len = slides.length; i < len; i++) {
sizes.w += slides[i].offsetWidth;
sizes.h = Math.max(sizes.h, slides[i].offsetHeight);
var ml = null;
var mr = null;
if ( i === 0 ) {
_pl = parseInt(pad.pl, 10);
ml = this.itemLeftOffset + _pl + 'px';
mr = this.itemOffsetSide + 'px';
}else if (i !== 0 && i !== len - 1 ) {
ml = this.itemOffsetSide + 'px';
mr = this.itemOffsetSide + 'px';
}else{
_pr = parseInt(pad.pr, 10);
ml = this.itemOffsetSide + 'px';
mr = this.itemRightOffset + _pr + 'px';
}
slides[i].style.marginLeft = ml;
slides[i].style.marginRight = mr;
}
sizes.w += this.getSideOffsetCorrection(slides.length) + _pr + _pl;
sizes.topMargin = parseInt(pad.pt, 10);
sizes.bottomMargin = parseInt(pad.pb, 10);
return sizes;
}
StoriesSlider.prototype.getSideOffsetCorrection = function (amount) {
return this.itemOffsetSide * 2 * (amount - 1) + this.itemLeftOffset + this.itemRightOffset;
}
StoriesSlider.prototype.createSlidesWrapper = function () {
this.slidesWrapper = document.createElement('div');
this.slidesWrapper.className = 'sts-wrapper';
this.slidesWrapper.setAttribute(this.dataAttributeName, this.dataAttributeValue);
var self = this;
return function (elements) {
elements.forEach(function(el) {
self.slidesWrapper.appendChild(el);
});
}
}
StoriesSlider.prototype.setSizesOnSlidesWrapper = function (sizes) {
this.slidesWrapper.style.width = sizes.w + 'px';
this.slidesWrapper.style.height = sizes.h + 'px';
this.slidesWrapper.style.marginTop = sizes.topMargin + 'px';
this.slidesWrapper.style.marginBottom = sizes.bottomMargin + 'px';
this.containerEl.style.height = sizes.h + sizes.topMargin + sizes.bottomMargin + 'px';
}
StoriesSlider.prototype.setSlidesOnSlidesWrapper = function (wrapperSeter, slides) {
wrapperSeter(slides);
}
StoriesSlider.prototype.setWrapperOnContainer = function (wrap) {
this.containerEl.appendChild(wrap)
}
StoriesSlider.prototype.setDiffBetweenContainerAndSlidesWrapper = function () {
this.diffBetweenContainerAndSlidesWrapper = this.containerEl.clientWidth - this.slidesWrapper.clientWidth;
}
StoriesSlider.prototype.checkBorder = function (fn) {
if ( this.isBorder ) {
return false;
}else{
fn.call(this);
this.isBorder = true;
}
}
StoriesSlider.prototype.getLeftPosition = function () {
return this.slidesWrapper.getBoundingClientRect().left - this.containerEl.getBoundingClientRect().left
}
StoriesSlider.prototype.setRAF = function () {
this._watcher();
this._updater(function(){
this.offsetForAnimation = Math.abs(this.offset) <= this.minDragDistance ? this.offset : this.offset / 25;
this.pos = this.tran + parseInt(this.offset.toFixed(3), 10);
});
this.leftPosition = this.getLeftPosition();
this.dir = this.offset >= 0 ? 1 : -1;
if (!this.isDrag && this.tran !== 0) {
this.tran += (this.offsetForAnimation *= this.inertionCoef);
this.pos = this.tran;
}
if ( this.leftPosition >= 0 && this.diffBetweenContainerAndSlidesWrapper < 0) {
if(!!this._ls) {
this.isBorder = false;
}else{
this.isBorder = true;
}
this.checkBorder(function () {
this._ls();
});
}
if ( this.leftPosition > 0 && this.dir > 0 ) {
this.isBorder = false;
this.isGateOpen = false;
this.isDrag = false
this.tran = 0;
this.pos = 0;
this.offset = 0;
this.offsetForAnimation = 0;
this.checkBorder(function () {
this._ls();
});
} if ( this.diffBetweenContainerAndSlidesWrapper >= this.leftPosition && this.dir < 0 ) {
this.isBorder = false;
this.isGateOpen = false;
this.isDrag = false;
this.tran = this.leftPosition;
this.pos = this.leftPosition;
this.offset = 0;
this.offsetForAnimation = 0;
this.checkBorder(function () {
this._rs();
});
} if (this.diffBetweenContainerAndSlidesWrapper < this.leftPosition && this.leftPosition < 0) {
this.checkBorder(function () {
this._md();
});
}
this.moveContainer(this.pos);
requestAnimationFrame(this.setRAF);
}
StoriesSlider.prototype.isLeftSide = function (callback) {
this._ls = callback;
}
StoriesSlider.prototype.isRightSide = function (callback) {
this._rs = callback;
}
StoriesSlider.prototype.isMedium = function (callback) {
this._md = callback;
}
StoriesSlider.prototype.moveContainer = function (offset) {
this.slidesWrapper.style.transform = 'translate3d('+ offset +'px, 0, 0)';
}
StoriesSlider.prototype.getEvent = function (e) {
return !!e.targetTouches ? e.targetTouches[0].clientX : e.clientX;
}
StoriesSlider.prototype.down = function (e) {
if (this.isClickPrevent){
e.preventDefault();
e.stopPropagation();
}
this.canInteract = true;
this.isDrag = true;
this.referencePoint = this.getEvent(e);
}
StoriesSlider.prototype.up = function (e) {
this.isClickPrevent = false;
//e.preventDefault();
//e.stopPropagation();
this.isDrag = false;
this.tran = this.pos;
}
StoriesSlider.prototype.move = function (e) {
this.isClickPrevent = true;
e.preventDefault();
e.stopPropagation();
this.canInteract = false;
this.isBorder = false;
if( this.isDrag && !this.isGateOpen ) {
this.offset = this.getEvent(e) - this.referencePoint;
this.offsetForAnimation = Math.abs(this.offset) <= this.minDragDistance ? this.offset : this.offset / 8;
this.pos = this.tran + parseInt(this.offset.toFixed(3), 10);
}
}
StoriesSlider.prototype.setSliderMotion = function (direction) {
if (this.isGateOpen){
return false;
}
var self = this;
this.offset = 0
this.isBorder = false;
this.dir = direction;
this.isGateOpen = true;
this.isDrag = true;
setTimeout(function(){
self.isGateOpen = false;
self.isDrag = false;
self.tran = self.pos;
},500);
}
StoriesSlider.prototype.moveLeft = function () {
this.setSliderMotion(1)
}
StoriesSlider.prototype.moveRight = function () {
this.setSliderMotion(-1)
}
StoriesSlider.prototype.controller = function (wrap) {
var self = this;
this.slidesWrapper.addEventListener('mousedown', function (e) {
self.down(e);
});
this.slidesWrapper.addEventListener('mouseup', function (e) {
self.up(e);
});
this.slidesWrapper.addEventListener('mousemove', function (e) {
self.move(e);
});
this.slidesWrapper.addEventListener('mouseleave', function (e) {
self.up(e);
});
/***************************************************************/
this.slidesWrapper.addEventListener('touchstart', function (e) {
self.down(e)
});
this.slidesWrapper.addEventListener('touchmove', function (e) {
self.move(e);
});
this.slidesWrapper.addEventListener('touchend', function (e) {
self.up(e);
});
}
var slider = new StoriesSlider({
container: '.container',
itemLeftOffset: 5,
itemRightOffset: 5,
itemOffsetSide: 5,
minDragDistance: 10,
useIsideController: false,
inertionCoef: 0.93
});
var el = $('[data-sts]');
el.on('mousedown touchstart', function (e) {
slider.down(e)
});
el.on('mousemove touchmove', function (e) {
slider.move(e)
});
el.on('mouseup', function (e) {
slider.up(e)
});
el.on('mouseleave touchend', function (e) {
slider.up(e)
});
function showButtons () {
var prev = document.querySelector('.prev');
var next = document.querySelector('.next');
return function (type) {
if (type === 'left') {
next.classList.add('nav-btn--active');
prev.classList.remove('nav-btn--active');
}
if (type === 'right'){
next.classList.remove('nav-btn--active');
prev.classList.add('nav-btn--active');
}
if(type === 'medium'){
next.classList.add('nav-btn--active');
prev.classList.add('nav-btn--active');
}
}
}
var setActionsState = showButtons();
slider.isLeftSide(function () {
setActionsState('left')
});
slider.isRightSide(function () {
setActionsState('right')
});
slider.isMedium(function () {
setActionsState('medium')
});
var prev = document.querySelector('.prev');
var next = document.querySelector('.next');
prev.addEventListener('click', function () {
slider.moveLeft();
});
next.addEventListener('click', function () {
slider.moveRight();
});
//console.log( a ? a : !isNaN(+a) ? a : null );
$(document).on('click', 'img', function (e) {
if($(this).attr('src') && slider.getInteractPossibility() ) {
createLB('photo', $(this).attr('src'))
}
});
$(document).on('click', '.ld-lightbox__close, .ld-lightbox', function () {
$('.ld-lightbox').css({opacity: 0});
setTimeout(function () {
closeLB();
},300);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://codepen.io/fdsea/pen/RvRwWP.js"></script>
$size: 90px
html,
body
width: 100%
height: 100%
padding: 0
margin: 0
box-sizing: border-box
*,*:before,*:after
box-sizing: inherit
/****************************/
.inside-wrapper
max-width: 700px
margin: 0 auto
position: relative
top: 50%
transform: translateY(-50%)
border-radius: 20px 20px
overflow: hidden
.container
width: 100%
height: $size
overflow: hidden
position: relative
padding: 20px
.container-item
cursor: pointer
overflow: hidden
height: $size
width: $size
overflow: hidden
border-radius: 50%
position: relative
display: inline-block
box-shadow: 1px 3px 15px #222
z-index: 100
&:nth-child(1)
width: $size
height: $size
&:nth-child(4)
width: $size
img
width: 100%
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%)
cursor: pointer
/*SLIDER SELF STYLES*/
.sts-wrapper
position: absolute
top: 0
left: 0
cursor: pointer
/*SLIDER SELF STYLES*/
.ld
width: 100%
height: 100%
.prev,
.next
display: none
.nav-btn
top: 0
position: absolute
height: 100%
width: 80px
border: none
cursor: pointer
svg
position: absolute
top: 42%
&--active
display: block
.prev
left: 0px
border-radius: 20px 0 0 20px
background: linear-gradient(-90deg, rgba(255,255,255, 0.01) 10%, rgba(255,255,255, 1))
svg
left: 5px
.next
right: 0px
border-radius: 0 20px 20px 0
background: linear-gradient(90deg, rgba(255,255,255, 0.01) 10%, rgba(255,255,255, 1))
svg
right: 5px
.ld-lightbox
width: 100%
height: 100%
position: fixed
left: 0
top: 0
transition: 0.3s ease
background-color: rgba(0,0,0, 0.9)
overflow: auto
&__vl
height: 100%
position: absolute
left: 50%
transform: translate(-50%, 0%)
width: 100%
max-width: 600px
display: flex
&__content
display: inline-block
margin: auto auto
img,
video
height: auto
width: 100%
max-width: 600px
@media screen and (max-width: 800px)
.nav-btn
outline: none
.ld-lightbox__close
position: absolute
right: 20px
top: 20px
color: #fff
font-size: 1.3em
cursor: pointer
z-index: 1000
@media screen and (max-width: 700px)
.nav-btn
outline: none
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment