{"id":3440,"date":"2022-09-04T06:54:16","date_gmt":"2022-09-04T06:54:16","guid":{"rendered":"https:\/\/rengga.dev\/blog\/?p=3440"},"modified":"2023-06-10T11:35:04","modified_gmt":"2023-06-10T11:35:04","slug":"js-tutorial-slider-with-infinite-loop-with-drag-and-scroll-horizontal","status":"publish","type":"post","link":"https:\/\/rengga.dev\/blog\/js-tutorial-slider-with-infinite-loop-with-drag-and-scroll-horizontal\/","title":{"rendered":"JS Tutorial &#8211; Slider with Infinite Loop with Drag and Scroll Horizontal"},"content":{"rendered":"<p><span style=\"color: #ef3207;\"><a style=\"color: #ef3207;\" href=\"https:\/\/rengga.dev\/\" target=\"_blank\" rel=\"noopener\"><strong>Rengga Dev<\/strong><\/a> <\/span>&#8211; Try playing with the parameters on the gui to the right. The slider with infinite loop is just one effect of javascript.<\/p>\n<p><iframe style=\"width: 100%;\" title=\"JS Tutorial - Slider with Infinite Loop with Drag and Scroll Horizontal\" src=\"https:\/\/codepen.io\/renggagumilar\/embed\/QWrwjjm?default-tab=result&amp;theme-id=dark\" height=\"500\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\"><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/renggagumilar\/pen\/QWrwjjm\"><br \/>\nJS Tutorial &#8211; Slider with Infinite Loop with Drag and Scroll Horizontal<\/a> by Rengga Gumilar (<a href=\"https:\/\/codepen.io\/renggagumilar\">@renggagumilar<\/a>)<br \/>\non <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<br \/>\n<\/iframe><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\/*--------------------\r\nVars\r\n--------------------*\/\r\nconst $menu = document.querySelector('.menu')\r\nconst $items = document.querySelectorAll('.menu--item')\r\nconst $images = document.querySelectorAll('.menu--item img')\r\nlet menuWidth = $menu.clientWidth\r\nlet itemWidth = $items[0].clientWidth\r\nlet wrapWidth = $items.length * itemWidth\r\n\r\nlet scrollSpeed = 0\r\nlet oldScrollY = 0\r\nlet scrollY = 0\r\nlet y = 0\r\n\r\n\r\n\/*--------------------\r\nLerp\r\n--------------------*\/\r\nconst lerp = (v0, v1, t) =&gt; {\r\n  return v0 * ( 1 - t ) + v1 * t\r\n}\r\n\r\n\r\n\/*--------------------\r\nDispose\r\n--------------------*\/\r\nconst dispose = (scroll) =&gt; {\r\n  gsap.set($items, {\r\n    x: (i) =&gt; {\r\n      return i * itemWidth + scroll\r\n    },\r\n    modifiers: {\r\n      x: (x, target) =&gt; {\r\n        const s = gsap.utils.wrap(-itemWidth, wrapWidth - itemWidth, parseInt(x))\r\n        return `${s}px`\r\n      }\r\n    }\r\n  })\r\n} \r\ndispose(0)\r\n\r\n\r\n\/*--------------------\r\nWheel\r\n--------------------*\/\r\nconst handleMouseWheel = (e) =&gt; {\r\n  scrollY -= e.deltaY * 0.9\r\n}\r\n\r\n\r\n\/*--------------------\r\nTouch\r\n--------------------*\/\r\nlet touchStart = 0\r\nlet touchX = 0\r\nlet isDragging = false\r\nconst handleTouchStart = (e) =&gt; {\r\n  touchStart = e.clientX || e.touches[0].clientX\r\n  isDragging = true\r\n  $menu.classList.add('is-dragging')\r\n}\r\nconst handleTouchMove = (e) =&gt; {\r\n  if (!isDragging) return\r\n  touchX = e.clientX || e.touches[0].clientX\r\n  scrollY += (touchX - touchStart) * 2.5\r\n  touchStart = touchX\r\n}\r\nconst handleTouchEnd = () =&gt; {\r\n  isDragging = false\r\n  $menu.classList.remove('is-dragging')\r\n}\r\n\r\n\r\n\/*--------------------\r\nListeners\r\n--------------------*\/\r\n$menu.addEventListener('mousewheel', handleMouseWheel)\r\n\r\n$menu.addEventListener('touchstart', handleTouchStart)\r\n$menu.addEventListener('touchmove', handleTouchMove)\r\n$menu.addEventListener('touchend', handleTouchEnd)\r\n\r\n$menu.addEventListener('mousedown', handleTouchStart)\r\n$menu.addEventListener('mousemove', handleTouchMove)\r\n$menu.addEventListener('mouseleave', handleTouchEnd)\r\n$menu.addEventListener('mouseup', handleTouchEnd)\r\n\r\n$menu.addEventListener('selectstart', () =&gt; { return false })\r\n\r\n\r\n\/*--------------------\r\nResize\r\n--------------------*\/\r\nwindow.addEventListener('resize', () =&gt; {\r\n  menuWidth = $menu.clientWidth\r\n  itemWidth = $items[0].clientWidth\r\n  wrapWidth = $items.length * itemWidth\r\n})\r\n\r\n\r\n\/*--------------------\r\nRender\r\n--------------------*\/\r\nconst render = () =&gt; {\r\n  requestAnimationFrame(render)\r\n  y = lerp(y, scrollY, .1)\r\n  dispose(y)\r\n  \r\n  scrollSpeed = y - oldScrollY\r\n  oldScrollY = y\r\n  \r\n  gsap.to($items, {\r\n    skewX: -scrollSpeed * .2,\r\n    rotate: scrollSpeed * .01,\r\n    scale: 1 - Math.min(100, Math.abs(scrollSpeed)) * 0.003\r\n  })\r\n}\r\nrender()\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Rengga Dev &#8211; Try playing with the parameters on the gui to <a class=\"read-more\" href=\"https:\/\/rengga.dev\/blog\/js-tutorial-slider-with-infinite-loop-with-drag-and-scroll-horizontal\/\" title=\"JS Tutorial &#8211; Slider with Infinite Loop with Drag and Scroll Horizontal\" itemprop=\"url\"><\/a><\/p>\n","protected":false},"author":1,"featured_media":3551,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"quote","meta":{"footnotes":""},"categories":[20],"tags":[325,337,264,263,103,227,265],"newstopic":[],"class_list":{"0":"post-3440","1":"post","2":"type-post","3":"status-publish","4":"format-quote","5":"has-post-thumbnail","7":"category-javascript","8":"tag-background-effects","9":"tag-infinite-loop","10":"tag-javascript-tutorial","11":"tag-js-tutorial","12":"tag-web-design","13":"tag-web-designer","14":"tag-webgl","15":"post_format-post-format-quote"},"_links":{"self":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts\/3440","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/comments?post=3440"}],"version-history":[{"count":1,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts\/3440\/revisions"}],"predecessor-version":[{"id":3441,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts\/3440\/revisions\/3441"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/media\/3551"}],"wp:attachment":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/media?parent=3440"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/categories?post=3440"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/tags?post=3440"},{"taxonomy":"newstopic","embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/newstopic?post=3440"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}