Skip to content

Instantly share code, notes, and snippets.

@steevehook
Last active October 24, 2018 10:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steevehook/4e6bade50eaba9e59051c9760f547627 to your computer and use it in GitHub Desktop.
Save steevehook/4e6bade50eaba9e59051c9760f547627 to your computer and use it in GitHub Desktop.
Vanilla carousel with infinite loop
export default {
lazyLoad: async () => {
const elList = document.querySelectorAll('.refresh-carousel');
if (elList.length > 0) {
const {default: carousel} = await import('./carousel');
elList.forEach(el => carousel(el));
}
}
};
import Hammer from 'hammerjs';
import {slide, activePrev, activeNext} from './moves';
export default metadata => {
const {com, wrapper} = metadata;
const sliderManager = new Hammer.Manager(wrapper);
const reposition = e => metadata.position + e.deltaX;
sliderManager.add(new Hammer.Pan({
threshold: 10,
pointers: 1,
direction: Hammer.DIRECTION_HORIZONTAL
}));
sliderManager.on('panstart', e => {
if (e.pointerType !== 'touch') {
return;
}
com.carousel.style.transition = 'none';
});
sliderManager.on('panleft panright', e => {
const isHorizontalPos = Math.abs(e.deltaX) > Math.abs(e.deltaY);
if (e.pointerType !== 'touch' || !isHorizontalPos) {
return;
}
slide({com, position: reposition(e)});
});
sliderManager.on('panend', e => {
let increment = Math.round(Math.abs(e.deltaX / metadata.slideWidth));
metadata.increment = increment === 0 ? 1 : increment;
const isHorizontal = Math.abs(e.deltaX) > Math.abs(e.deltaY);
if (e.pointerType !== 'touch' || !isHorizontal) {
return;
}
metadata.position = reposition(e);
com.carousel.style.transition = 'all .3s ease-in-out';
if (e.direction === Hammer.DIRECTION_LEFT || e.deltaX * 1 < 0) {
metadata.position -= (metadata.slideWidth * metadata.increment - Math.abs(e.deltaX));
activeNext(metadata);
} else if (e.direction === Hammer.DIRECTION_RIGHT || e.deltaX * 1 > 0) {
metadata.position += (metadata.slideWidth * metadata.increment - Math.abs(e.deltaX));
activePrev(metadata);
}
slide(metadata);
metadata.increment = 1;
});
}
const getSrcSet = image => {
if (!image || !image.srcset) {
return [];
}
return image.srcset.split(',').map(link => {
const [url, ratio] = link.trim().split` `;
const splitLink = url.split`/`;
return {
ratio,
width: splitLink[splitLink.length - 1]
};
});
};
export default (slide, metadata) => {
const {gallery} = metadata;
const lastLoadedSlide = metadata.loadedSlides[metadata.loadedSlides.length - 1];
const [gallerySample] = gallery[0].children[0].children;
if (slide > gallery.length - 1) {
return;
}
for (let i = lastLoadedSlide; i <= slide; i++) {
const [slideElement] = gallery[i].children,
[slideImage] = slideElement.children,
kalturaEntry = slideImage.dataset.kalturaEntry;
const sampleSrc = gallerySample.src.trim().split`/`,
sampleSrcWidth = sampleSrc[sampleSrc.length - 1];
if (!slideImage.src) {
slideImage.src = `${window.GHD.config.kalturaThumbnailURL}/${kalturaEntry}/width/${sampleSrcWidth}`;
slideImage.srcset = getSrcSet(gallerySample).map(v =>
`${window.GHD.config.kalturaThumbnailURL}/${kalturaEntry}/quality/75/width/${v.width} ${v.ratio}`
);
slideImage.sizes = gallerySample.sizes;
metadata.loadedSlides.push(i);
}
}
};
export default element => {
const wrapper = element.parentElement.parentElement;
const position = 0;
const numberOfSlides = parseInt(element.dataset.numberOfSlides);
const slideWidth = window.innerWidth / numberOfSlides;
const loadedSlides = [numberOfSlides];
const com = {
carousel: element,
titleList: element.querySelectorAll('.refresh-content-images__info-title'),
leftArrow: wrapper.querySelector('.refresh-content-images__arrow--left'),
rightArrow: wrapper.querySelector('.refresh-content-images__arrow--right')
};
const gallery = Array
.from(com.carousel.children || [])
.filter(e => e.classList.contains('refresh-content-images__list-item'));
const active = 0;
const stepPos = 0;
const increment = 1;
return {
wrapper,
position,
numberOfSlides,
slideWidth,
loadedSlides,
com,
gallery,
active,
stepPos,
increment
};
};
import lazyLoad from './lazyLoad';
export const slide = ({com, position}) => {
com.carousel.style.left = position + 'px';
};
export const step = (metadata, time) => {
setTimeout(() => {
for (let i = 0; i < metadata.gallery.length; i++) {
const index = (metadata.active + i) % metadata.gallery.length;
const slide = metadata.com.carousel.children[index];
slide.style.position = 'absolute';
slide.style.left = `${metadata.slideWidth * i + metadata.stepPos}px`;
}
}, time || 0);
};
export const activeNext = metadata => {
metadata.stepPos += metadata.slideWidth * metadata.increment;
metadata.com.carousel.children[metadata.active].classList.remove('active');
metadata.active = metadata.active + metadata.increment > metadata.com.carousel.children.length - 1 ? 0 : metadata.active + metadata.increment;
metadata.com.carousel.children[metadata.active].classList.add('active');
step(metadata, 300);
lazyLoad(metadata.active + metadata.numberOfSlides - 1, metadata);
};
export const activePrev = metadata => {
metadata.stepPos -= metadata.slideWidth * metadata.increment;
metadata.com.carousel.children[metadata.active].classList.remove('active');
metadata.active = metadata.active - metadata.increment < 0 ? metadata.com.carousel.children.length - 1 : metadata.active - metadata.increment;
metadata.com.carousel.children[metadata.active].classList.add('active');
step(metadata, 0);
lazyLoad(metadata.active, metadata);
};
export const nextHandler = metadata => {
const {com, slideWidth} = metadata;
activeNext(metadata);
metadata.position -= slideWidth * metadata.increment;
slide({com, position: metadata.position});
};
export const previousHandler = metadata => {
const {com, slideWidth} = metadata;
activePrev(metadata);
metadata.position += slideWidth * metadata.increment;
slide({com, position: metadata.position});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment