Rengga Dev – Try playing with the parameters on the gui to the right. The Drag and Scroll Carousel Slider is just one effect of javascript.
const lerp = (f0, f1, t) => (1 - t) * f0 + t * f1 const clamp = (val, min, max) => Math.max(min, Math.min(val, max)) class DragScroll { constructor(obj) { this.$el = document.querySelector(obj.el) this.$wrap = this.$el.querySelector(obj.wrap) this.$items = this.$el.querySelectorAll(obj.item) this.$bar = this.$el.querySelector(obj.bar) this.init() } init() { this.progress = 0 this.speed = 0 this.oldX = 0 this.x = 0 this.playrate = 0 // this.bindings() this.events() this.calculate() this.raf() } bindings() { [ 'events', 'calculate', 'raf', 'handleWheel', 'move', 'raf', 'handleTouchStart', 'handleTouchMove', 'handleTouchEnd' ].forEach(i => { this[i] = this[i].bind(this) }) } calculate() { this.progress = 0 this.wrapWidth = this.$items[0].clientWidth * this.$items.length this.$wrap.style.width = `${this.wrapWidth}px` this.maxScroll = this.wrapWidth - this.$el.clientWidth } handleWheel(e) { this.progress += e.deltaY this.move() } handleTouchStart(e) { e.preventDefault() this.dragging = true this.startX = e.clientX || e.touches[0].clientX this.$el.classList.add('dragging') } handleTouchMove(e) { if (!this.dragging) return false const x = e.clientX || e.touches[0].clientX this.progress += (this.startX - x) * 2.5 this.startX = x this.move() } handleTouchEnd() { this.dragging = false this.$el.classList.remove('dragging') } move() { this.progress = clamp(this.progress, 0, this.maxScroll) } events() { window.addEventListener('resize', this.calculate) window.addEventListener('wheel', this.handleWheel) // this.$el.addEventListener('touchstart', this.handleTouchStart) window.addEventListener('touchmove', this.handleTouchMove) window.addEventListener('touchend', this.handleTouchEnd) // window.addEventListener('mousedown', this.handleTouchStart) window.addEventListener('mousemove', this.handleTouchMove) window.addEventListener('mouseup', this.handleTouchEnd) document.body.addEventListener('mouseleave', this.handleTouchEnd) } raf() { // requestAnimationFrame(this.raf) this.x = lerp(this.x, this.progress, 0.1) this.playrate = this.x / this.maxScroll // this.$wrap.style.transform = `translateX(${-this.x}px)` this.$bar.style.transform = `scaleX(${.18 + this.playrate * .82})` // this.speed = Math.min(100, this.oldX - this.x) this.oldX = this.x // this.scale = lerp(this.scale, this.speed, 0.1) this.$items.forEach(i => { i.style.transform = `scale(${1 - Math.abs(this.speed) * 0.002})` i.querySelector('img').style.transform = `scaleX(${1 + Math.abs(this.speed) * 0.004})` }) } } /*-------------------- Instances --------------------*/ const scroll = new DragScroll({ el: '.carousel', wrap: '.carousel--wrap', item: '.carousel--item', bar: '.carousel--progress-bar', }) /*-------------------- One raf to rule em all --------------------*/ const raf = () => { requestAnimationFrame(raf) scroll.raf() } raf()