{"id":326,"date":"2023-03-08T00:07:55","date_gmt":"2023-03-07T21:07:55","guid":{"rendered":"https:\/\/notes.profidev.online\/?p=326"},"modified":"2023-03-28T23:47:36","modified_gmt":"2023-03-28T20:47:36","slug":"karusel","status":"publish","type":"post","link":"https:\/\/notes.profidev.online\/ru\/slider\/326\/","title":{"rendered":"Carousel"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"741\" style=\"aspect-ratio: 1395 \/ 741;\" width=\"1395\" controls src=\"https:\/\/notes.profidev.online\/wp-content\/uploads\/2023\/03\/vokoscreenng-2023-03-07_22-09-17.webm\"><\/video><\/figure>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;htmlmixed&quot;,&quot;mime&quot;:&quot;text\/html&quot;,&quot;theme&quot;:&quot;cobalt&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:false,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;HTML&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;html&quot;}\">&lt;div class=&quot;gallery&quot;&gt;\n\t&lt;ul class=&quot;cards&quot;&gt;\n\t\t&lt;li&gt;0&lt;\/li&gt;\n\t\t&lt;li&gt;1&lt;\/li&gt;\n\t\t&lt;li&gt;2&lt;\/li&gt;\n\t\t&lt;li&gt;3&lt;\/li&gt;\n\t\t&lt;li&gt;4&lt;\/li&gt;\n\t\t&lt;li&gt;5&lt;\/li&gt;\n\t\t&lt;li&gt;6&lt;\/li&gt;\n\t\t&lt;li&gt;7&lt;\/li&gt;\n\t\t&lt;li&gt;8&lt;\/li&gt;\n\t\t&lt;li&gt;9&lt;\/li&gt;\n\t\t&lt;li&gt;10&lt;\/li&gt;\n\t&lt;\/ul&gt;\n\t&lt;div class=&quot;actions&quot;&gt;\n\t\t&lt;button class=&quot;prev&quot;&gt;Prev&lt;\/button&gt;\n\t\t&lt;button class=&quot;next&quot;&gt;Next&lt;\/button&gt;\n\t&lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;script src=&quot;https:\/\/unpkg.co\/gsap@3\/dist\/gsap.min.js&quot;&gt;&lt;\/script&gt;\n&lt;script src=&quot;https:\/\/unpkg.com\/gsap@3\/dist\/ScrollTrigger.min.js&quot;&gt;&lt;\/script&gt;\n\/\/\u0421\u043a\u0440\u0438\u043f\u0442 Js \u043d\u0430\u0434\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c\n\/\/\u0410\u0432\u0442\u043e\u0440: Stephen Scaff. @StephenScaff<\/pre><\/div>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;css&quot;,&quot;mime&quot;:&quot;text\/css&quot;,&quot;theme&quot;:&quot;cobalt&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:false,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;CSS&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;css&quot;}\">* {\n\tbox-sizing: border-box;\n}\nbody {\n\tbackground: #111;\n\tmin-height: 100vh;\n\tpadding: 0;\n\tmargin: 0;\n}\n.gallery {\n\tposition: absolute;\n\twidth: 100%;\n\theight: 100vh;\n\toverflow: hidden;\n}\n\n.cards {\n\tposition: absolute;\n\twidth: 14rem;\n\theight: 18rem;\n\ttop: 40%;\n\tleft: 50%;\n\ttransform: translate(-50%, -50%);\n}\n\n.cards li {\n\tlist-style: none;\n\tpadding: 0;\n\tmargin: 0;\n\twidth: 14rem;\n\theight: 18rem;\n\ttext-align: center;\n\tline-height: 18rem;\n\tfont-size: 2rem;\n\tfont-family: sans-serif;\n\tbackground-color: #31f93e;\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tborder-radius: 0.8rem;\n}\n\n.actions {\n\tposition: absolute;\n\tbottom: 25px;\n\tleft: 50%;\n\ttransform: translateX(-50%);\n}\n\nbutton {\n  display:inline-block;\n  outline: none;\n  border: none;\n  padding: 8px 14px;\n  background: #414141;\n  background-image: -webkit-linear-gradient(top, #575757, #414141);\n  background-image: -moz-linear-gradient(top, #575757, #414141);\n  background-image: -ms-linear-gradient(top, #575757, #414141);\n  background-image: -o-linear-gradient(top, #575757, #414141);\n  background-image: linear-gradient(to bottom, #575757, #414141);\n  text-shadow: 0px 1px 0px #414141;\n  -webkit-box-shadow: 0px 1px 0px 414141;\n  -moz-box-shadow: 0px 1px 0px 414141;\n  box-shadow: 0px 1px 0px 414141;\n  color: #ffffff;\n  text-decoration: none;\n  margin: 0 auto 10px;\n  -webkit-border-radius: 4;\n  -moz-border-radius: 4;\n  border-radius: 4px;\n  padding: 12px 25px;\n  font-family: &quot;Signika Negative&quot;, sans-serif;\n  text-transform: uppercase;\n  font-weight: 600;\n  cursor: pointer;\n  font-size: 13px;\n  line-height: 18px;\n}\n\nbutton:hover {\n  background: #57a818;\n  background-image: -webkit-linear-gradient(top, #57a818, #4d9916);\n  background-image: -moz-linear-gradient(top, #57a818, #4d9916);\n  background-image: -ms-linear-gradient(top, #57a818, #4d9916);\n  background-image: -o-linear-gradient(top, #57a818, #4d9916);\n  background-image: linear-gradient(to bottom, #57a818, #4d9916);\n  text-shadow: 0px 1px 0px #32610e;\n  -webkit-box-shadow: 0px 1px 0px fefefe;\n  -moz-box-shadow: 0px 1px 0px fefefe;\n  box-shadow: 0px 1px 0px fefefe;\n  color: #ffffff;\n  text-decoration: none;\n}\n\nbutton {\n  font-size: 20px;\n  font-weight: 400;\n}\n\na {\n  color: #88ce02;\n  text-decoration: none;\n}\na:hover {\n  text-decoration: underline;\n}<\/pre><\/div>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;javascript&quot;,&quot;mime&quot;:&quot;text\/javascript&quot;,&quot;theme&quot;:&quot;cobalt&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:false,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;JavaScript&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;js&quot;}\">gsap.registerPlugin(ScrollTrigger);\n\nlet iteration = 0; \/\/ gets iterated when we scroll all the way to the end or start and wraps around - allows us to smoothly continue the playhead scrubbing in the correct direction.\n\nconst spacing = 0.1,    \/\/ spacing of the cards (stagger)\n\tsnap = gsap.utils.snap(spacing), \/\/ we'll use this to snap the playhead on the seamlessLoop\n\tcards = gsap.utils.toArray('.cards li'),\n\tseamlessLoop = buildSeamlessLoop(cards, spacing),\n\tscrub = gsap.to(seamlessLoop, { \/\/ we reuse this tween to smoothly scrub the playhead on the seamlessLoop\n\t\ttotalTime: 0,\n\t\tduration: 0.5,\n\t\tease: &quot;power3&quot;,\n\t\tpaused: true\n\t}),\n\ttrigger = ScrollTrigger.create({\n\t\tstart: 0,\n\t\tonUpdate(self) {\n\t\t\tif (self.progress === 1 &amp;&amp; self.direction &gt; 0 &amp;&amp; !self.wrapping) {\n\t\t\t\twrapForward(self);\n\t\t\t} else if (self.progress &lt; 1e-5 &amp;&amp; self.direction &lt; 0 &amp;&amp; !self.wrapping) {\n\t\t\t\twrapBackward(self);\n\t\t\t} else {\n        scrub.vars.totalTime = snap((iteration + self.progress) * seamlessLoop.duration());\n\t\t\t\tscrub.invalidate().restart(); \/\/ to improve performance, we just invalidate and restart the same tween. No need for overwrites or creating a new tween on each update.\n\t\t\t\tself.wrapping = false;\n\t\t\t}\n\t\t},\n\t\tend: &quot;+=3000&quot;,\n\t\tpin: &quot;.gallery&quot;\n\t});\n\nfunction wrapForward(trigger) { \/\/ when the ScrollTrigger reaches the end, loop back to the beginning seamlessly\n\titeration++;\n\ttrigger.wrapping = true;\n\ttrigger.scroll(trigger.start + 1);\n}\n\nfunction wrapBackward(trigger) { \/\/ when the ScrollTrigger reaches the start again (in reverse), loop back to the end seamlessly\n\titeration--;\n\tif (iteration &lt; 0) { \/\/ to keep the playhead from stopping at the beginning, we jump ahead 10 iterations\n\t\titeration = 9;\n\t\tseamlessLoop.totalTime(seamlessLoop.totalTime() + seamlessLoop.duration() * 10);\n    scrub.pause(); \/\/ otherwise it may update the totalTime right before the trigger updates, making the starting value different than what we just set above. \n\t}\n\ttrigger.wrapping = true;\n\ttrigger.scroll(trigger.end - 1);\n}\n\nfunction scrubTo(totalTime) { \/\/ moves the scroll position to the place that corresponds to the totalTime value of the seamlessLoop, and wraps if necessary.\n\tlet progress = (totalTime - seamlessLoop.duration() * iteration) \/ seamlessLoop.duration();\n\tif (progress &gt; 1) {\n\t\twrapForward(trigger);\n\t} else if (progress &lt; 0) {\n\t\twrapBackward(trigger);\n\t} else {\n\t\ttrigger.scroll(trigger.start + progress * (trigger.end - trigger.start));\n\t}\n}\n\ndocument.querySelector(&quot;.next&quot;).addEventListener(&quot;click&quot;, () =&gt; scrubTo(scrub.vars.totalTime + spacing));\ndocument.querySelector(&quot;.prev&quot;).addEventListener(&quot;click&quot;, () =&gt; scrubTo(scrub.vars.totalTime - spacing));\n\n\n\n\nfunction buildSeamlessLoop(items, spacing) {\n\tlet overlap = Math.ceil(1 \/ spacing), \/\/ number of EXTRA animations on either side of the start\/end to accommodate the seamless looping\n\t\tstartTime = items.length * spacing + 0.5, \/\/ the time on the rawSequence at which we'll start the seamless loop\n\t\tloopTime = (items.length + overlap) * spacing + 1, \/\/ the spot at the end where we loop back to the startTime \n\t\trawSequence = gsap.timeline({paused: true}), \/\/ this is where all the &quot;real&quot; animations live\n\t\tseamlessLoop = gsap.timeline({ \/\/ this merely scrubs the playhead of the rawSequence so that it appears to seamlessly loop\n\t\t\tpaused: true,\n\t\t\trepeat: -1, \/\/ to accommodate infinite scrolling\/looping\n\t\t\tonRepeat() { \/\/ works around a super rare edge case bug that's fixed GSAP 3.6.1\n\t\t\t\tthis._time === this._dur &amp;&amp; (this._tTime += this._dur - 0.01);\n\t\t\t}\n\t\t}),\n\t\tl = items.length + overlap * 2,\n\t\ttime = 0,\n\t\ti, index, item;\n\n\t\/\/ set initial state of items\n\tgsap.set(items, {xPercent: 400, opacity: 0,\tscale: 0});\n\n\t\/\/ now loop through and create all the animations in a staggered fashion. Remember, we must create EXTRA animations at the end to accommodate the seamless looping.\n\tfor (i = 0; i &lt; l; i++) {\n\t\tindex = i % items.length;\n\t\titem = items[index];\n\t\ttime = i * spacing;\n\t\trawSequence.fromTo(item, {scale: 0, opacity: 0}, {scale: 1, opacity: 1, zIndex: 100, duration: 0.5, yoyo: true, repeat: 1, ease: &quot;power1.in&quot;, immediateRender: false}, time)\n\t\t           .fromTo(item, {xPercent: 400}, {xPercent: -400, duration: 1, ease: &quot;none&quot;, immediateRender: false}, time);\n\t\ti &lt;= items.length &amp;&amp; seamlessLoop.add(&quot;label&quot; + i, time); \/\/ we don't really need these, but if you wanted to jump to key spots using labels, here ya go.\n\t}\n\t\n\t\/\/ here's where we set up the scrubbing of the playhead to make it appear seamless. \n\trawSequence.time(startTime);\n\tseamlessLoop.to(rawSequence, {\n\t\ttime: loopTime,\n\t\tduration: loopTime - startTime,\n\t\tease: &quot;none&quot;\n\t}).fromTo(rawSequence, {time: overlap * spacing + 1}, {\n\t\ttime: startTime,\n\t\tduration: startTime - (overlap * spacing + 1),\n\t\timmediateRender: false,\n\t\tease: &quot;none&quot;\n\t});\n\treturn seamlessLoop;\n}\n<\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":330,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21],"tags":[27],"class_list":["post-326","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-slider","tag-gsap"],"_links":{"self":[{"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/posts\/326","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/comments?post=326"}],"version-history":[{"count":0,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/posts\/326\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/media\/330"}],"wp:attachment":[{"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/media?parent=326"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/categories?post=326"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/notes.profidev.online\/ru\/wp-json\/wp\/v2\/tags?post=326"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}