From a3bacc6e0bb7ff26114a1c3325282b8ef4ce4da8 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sat, 19 Feb 2022 15:13:04 -0800 Subject: [PATCH 01/23] Stubbing out looping prop and docs --- README.md | 1 + demo/components/layout/nav.vue | 1 + demo/content/looping.md | 18 ++++++++++++++++++ src/concerns/looping.coffee | 8 ++++++++ src/ssr-carousel.vue | 2 ++ 5 files changed, 30 insertions(+) create mode 100644 demo/content/looping.md create mode 100644 src/concerns/looping.coffee diff --git a/README.md b/README.md index b6b4903..d5d63f6 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ For more examples, see the demo: https://vue-ssr-carousel.netlify.app. - `slides-per-page` (`1`) - How many slides are shown per page. - `gutter` (`20`) - The size of the space between slides. This can a number or any CSS resolvable string. See https://vue-ssr-carousel.netlify.app/gutters. - `responsive` (`[]`) - Adjust settings at breakpoints. See https://vue-ssr-carousel.netlify.app/responsive. +- `looping` (`false`) - Boolean to enable looping / infinite scroll. - `paginate-by-slide` (`false`) - When `false`, dragging the carousel or interacting with the arrows will advance a full page of slides at a time. When `true`, the carousel will come to a rest at each slide. - `show-arrows` (`false`) - Whether to show back/forward arrows. See https://vue-ssr-carousel.netlify.app/ui. - `show-dots` (`false`) - Whether to show dot style pagination dots. See https://vue-ssr-carousel.netlify.app/ui. diff --git a/demo/components/layout/nav.vue b/demo/components/layout/nav.vue index 2815e56..a769086 100644 --- a/demo/components/layout/nav.vue +++ b/demo/components/layout/nav.vue @@ -19,6 +19,7 @@ export default { title: 'Responsive', path: '/responsive' } { title: 'Gutters', path: '/gutters' } { title: 'UI', path: '/ui' } + { title: 'Looping', path: '/looping' } { title: 'Miscellaneous', path: '/misc' } ] diff --git a/demo/content/looping.md b/demo/content/looping.md new file mode 100644 index 0000000..672703c --- /dev/null +++ b/demo/content/looping.md @@ -0,0 +1,18 @@ +--- +title: 'Looping / Inifinte Scroll' +--- + +## Basic looping + + + + + + + +```vue + + + + + diff --git a/src/concerns/looping.coffee b/src/concerns/looping.coffee new file mode 100644 index 0000000..68fa523 --- /dev/null +++ b/src/concerns/looping.coffee @@ -0,0 +1,8 @@ +### +Code related to looping / infinite scroll +### +export default + + # Add prop to enable looping + props: + looping: Boolean diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index 8ccddd5..66ce024 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -51,6 +51,7 @@ import SsrCarouselTrack from './ssr-carousel-track' import autoplay from './concerns/autoplay' import dragging from './concerns/dragging' import focus from './concerns/focus' +import looping from './concerns/looping' import pagination from './concerns/pagination' import responsive from './concerns/responsive' import tweening from './concerns/tweening' @@ -64,6 +65,7 @@ export default autoplay dragging focus + looping pagination responsive tweening From 94e0c116bc83b30628479c8be9f67bfa5222df31 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sat, 19 Feb 2022 16:20:18 -0800 Subject: [PATCH 02/23] Initial implementation of cloneVnode --- src/concerns/looping.coffee | 41 ++++++++++++++++++++++++++++++++++ src/concerns/pagination.coffee | 2 +- src/ssr-carousel-track.vue | 5 +++-- src/ssr-carousel.vue | 4 +--- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/concerns/looping.coffee b/src/concerns/looping.coffee index 68fa523..31e094f 100644 --- a/src/concerns/looping.coffee +++ b/src/concerns/looping.coffee @@ -6,3 +6,44 @@ export default # Add prop to enable looping props: looping: Boolean + + # Store cloned slides + data: -> + prependedSlides: [] + appendedSlides: [] + + # Testing cloneVnode + created: -> + clone = @cloneVnode @$slots.default[1] + @prependedSlides.push clone + + computed: + + # Combine slotted slides and clones + slides: -> [...@prependedSlides, ...@$slots.default, ...@appendedSlides] + + methods: + + # Clone a vnode, based on + # https://github.com/vuejs/vue/blob/23760b5c7a350484ef1eee18f8c615027a8a8ad9/src/core/vdom/vnode.js#L89 + cloneVnode: (vnode) -> + cloned = new vnode.constructor( + vnode.tag, + vnode.data, + vnode.children && vnode.children.slice(), + vnode.text, + vnode.elm, + vnode.context, + vnode.componentOptions, + vnode.asyncFactory + ) + cloned.ns = vnode.ns + cloned.isStatic = vnode.isStatic + cloned.key = vnode.key + cloned.isComment = vnode.isComment + cloned.fnContext = vnode.fnContext + cloned.fnOptions = vnode.fnOptions + cloned.fnScopeId = vnode.fnScopeId + cloned.asyncMeta = vnode.asyncMeta + cloned.isCloned = true + return cloned diff --git a/src/concerns/pagination.coffee b/src/concerns/pagination.coffee index 112de35..8827dfe 100644 --- a/src/concerns/pagination.coffee +++ b/src/concerns/pagination.coffee @@ -27,7 +27,7 @@ export default # Filter out slides that have a "text" property, these aren't actual # elements. They are whitespace, like newlines. slidesCount: -> - (@$slots.default || []) + @slides .filter (vnode) -> !vnode?.text .length diff --git a/src/ssr-carousel-track.vue b/src/ssr-carousel-track.vue index 6370c08..ad85222 100644 --- a/src/ssr-carousel-track.vue +++ b/src/ssr-carousel-track.vue @@ -9,6 +9,7 @@ export default props: dragging: Boolean currentX: Number + slides: Array computed: @@ -19,8 +20,8 @@ export default render: (create) -> # Wrap the slides in ssr-carousel-slide functional components - children = @$slots.default.map (child) -> - if child.text then child # Text nodes like newlines + children = @slides.map (child) -> + unless child.tag then child # Text nodes like newlines else create SsrCarouselSlide, { parent: this }, [ child ] # Create the track div diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index 66ce024..ba31341 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -15,11 +15,9 @@ //- The container of the slides that animates ssr-carousel-track( ref='track' + :slides='slides' v-bind='{ dragging, currentX }') - //- Slides are injected here - slot - //- Back / Next navigation ssr-carousel-arrows( v-if='showArrows' From d3de0fe14d28238aa31a6b14d121062abccd5bde Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sat, 19 Feb 2022 16:21:50 -0800 Subject: [PATCH 03/23] CS --- src/ssr-carousel.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index ba31341..9badc7f 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -82,8 +82,11 @@ export default showDots: Boolean computed: + + # Determine whether to create hover event bindings watchesHover: -> @autoplayDelay > 0 + # Create event bindings maskListeners: -> return {} if @disabled { From 1f7a21a36674cbd3da7418d2bb4a5ba06cdb43cc Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sat, 19 Feb 2022 21:42:27 -0800 Subject: [PATCH 04/23] Testing nesting a component in a cloned vnode --- demo/components/slide.vue | 2 ++ demo/content/looping.md | 13 ++++++++++--- demo/package.json | 3 ++- demo/pages/_page.vue | 4 +++- demo/yarn.lock | 2 +- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/demo/components/slide.vue b/demo/components/slide.vue index 20bc501..add75be 100644 --- a/demo/components/slide.vue +++ b/demo/components/slide.vue @@ -36,6 +36,8 @@ export default flex-center() text-align center fluid-space padding 's' + > div + width 100% // Increase slide text size .title diff --git a/demo/content/looping.md b/demo/content/looping.md index 672703c..815523b 100644 --- a/demo/content/looping.md +++ b/demo/content/looping.md @@ -5,9 +5,15 @@ title: 'Looping / Inifinte Scroll' ## Basic looping - - - + + + + + + + + + ```vue @@ -16,3 +22,4 @@ title: 'Looping / Inifinte Scroll' +``` diff --git a/demo/package.json b/demo/package.json index 34ab1bf..5626e41 100644 --- a/demo/package.json +++ b/demo/package.json @@ -21,6 +21,7 @@ "prism-themes": "^1.9.0", "vue-balance-text": "^1.2.3", "vue-detachable-header": "^0.2.0", - "vue-unorphan": "^1.2.3" + "vue-unorphan": "^1.2.3", + "vue-visual": "^2.5.4" } } diff --git a/demo/pages/_page.vue b/demo/pages/_page.vue index 95f1a78..f1e51e4 100644 --- a/demo/pages/_page.vue +++ b/demo/pages/_page.vue @@ -21,12 +21,14 @@ article diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index 9badc7f..87be1e8 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -22,6 +22,7 @@ ssr-carousel-arrows( v-if='showArrows' v-bind='{ index, pages }' + :loop='loop' @back='back' @next='next') template(#back): slot(name='back-arrow') From 739ce155d0ef32edee82522eb03e6d61448f2429 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sat, 19 Feb 2022 22:39:03 -0800 Subject: [PATCH 09/23] Move arrows out of mask Closes #29. Also fixes issue where clicking on an arrow triggered the `mousedown` event on the mask --- src/ssr-carousel.vue | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index 87be1e8..17ab398 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -7,16 +7,21 @@ //- Render generated styles component(is='style' v-html='instanceStyles') - //- The overflow mask and drag target - .ssr-carousel-mask( - :class='{ pressing, disabled }' - v-on='maskListeners') - - //- The container of the slides that animates - ssr-carousel-track( - ref='track' - :slides='slides' - v-bind='{ dragging, currentX }') + //- Container so that arrows can be centered relative to slides but not be + //- within the mask's overflow:hidden (which prevents overriding styles from + //- positioning outside of carousel). + .ssr-carousel-slides + + //- The overflow mask and drag target + .ssr-carousel-mask( + :class='{ pressing, disabled }' + v-on='maskListeners') + + //- The container of the slides that animates + ssr-carousel-track( + ref='track' + :slides='slides' + v-bind='{ dragging, currentX }') //- Back / Next navigation ssr-carousel-arrows( @@ -109,6 +114,10 @@ export default .ssr-carousel touch-action pan-y +// Posiition arrows relative to this +.ssr-carousel-slides + position relative + // Mask around slides .ssr-carousel-mask overflow hidden From 8fdd1034a2efcd2052694a747a5720eb995d904f Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sat, 19 Feb 2022 22:40:48 -0800 Subject: [PATCH 10/23] Comment typos --- src/concerns/dragging.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/concerns/dragging.coffee b/src/concerns/dragging.coffee index 92cd67a..67304e7 100644 --- a/src/concerns/dragging.coffee +++ b/src/concerns/dragging.coffee @@ -41,9 +41,9 @@ export default computed: - # The current slide or page index. It rounds differently depedning on the + # The current slide or page index. It rounds differently depending on the # direction of the velocity. So that it eases to a stop in the direction - # the user was dragging + # the user was dragging. dragIndex: -> fractionalIndex = Math.abs if @paginateBySlide then @currentX / @slideWidth From c28dae92e0c0fd5f7b4c0c4c121d913e3b44b25d Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sat, 19 Feb 2022 22:41:08 -0800 Subject: [PATCH 11/23] Disable test cloneVnode code --- src/concerns/looping.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/concerns/looping.coffee b/src/concerns/looping.coffee index e01993b..6c02012 100644 --- a/src/concerns/looping.coffee +++ b/src/concerns/looping.coffee @@ -13,9 +13,9 @@ export default appendedSlides: [] # Testing cloneVnode - created: -> - clone = @cloneVnode @$slots.default[1] - @prependedSlides.push clone + # created: -> + # clone = @cloneVnode @$slots.default[1] + # @prependedSlides.push clone computed: From e8af12f306ae1fb79d03663415273c27e7b80934 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sat, 19 Feb 2022 22:41:30 -0800 Subject: [PATCH 12/23] Support index outside of the normal range when looping --- src/concerns/dragging.coffee | 7 +++++-- src/concerns/pagination.coffee | 15 +++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/concerns/dragging.coffee b/src/concerns/dragging.coffee index 67304e7..d8995b6 100644 --- a/src/concerns/dragging.coffee +++ b/src/concerns/dragging.coffee @@ -98,7 +98,7 @@ export default else # Tween so the track is in bounds if it was out - if @isOutOfBounds + if @isOutOfBounds and not @loop @targetX = @applyXBoundaries @currentX @startTweening() @@ -171,12 +171,15 @@ export default # Prevent dragging from exceeding the min/max edges applyBoundaryDampening: (x) -> switch + when @loop then x # Don't apply dampening when x > 0 then Math.pow x, @boundaryDampening when x < @endX then @endX - Math.pow @endX - x, @boundaryDampening else @applyXBoundaries x # Constraint the x value to the min and max values - applyXBoundaries: (x) -> Math.max @endX, Math.min 0, x + applyXBoundaries: (x) -> + if @loop then x # Don't apply boundaries + else Math.max @endX, Math.min 0, x # Prevent the anchors and images from being draggable (like via their # ghost outlines). Using this approach because the draggable html attribute diff --git a/src/concerns/pagination.coffee b/src/concerns/pagination.coffee index 302b8bc..2a168ff 100644 --- a/src/concerns/pagination.coffee +++ b/src/concerns/pagination.coffee @@ -9,7 +9,7 @@ export default paginateBySlide: Boolean data: -> - index: 0 # The current page + index: 0 # The current page; when looping may exceed slideCount currentX: 0 # The actual left offset of the slides container targetX: 0 # Where we may be tweening the slide to @@ -24,9 +24,8 @@ export default # Disable carousel-ness when there aren't enough slides disabled: -> @slidesCount <= @currentSlidesPerPage - # Filter out slides that have a "text" property, these aren't actual - # elements. They are whitespace, like newlines. - slidesCount: -> @slides.length + # Get the total number of slides + slidesCount: -> @slottedSlides.length watch: @@ -54,9 +53,5 @@ export default # Apply boundaries to the index applyIndexBoundaries: (index) -> - unless @loop - then Math.max 0, Math.min @pages - 1, index - else - if index < 0 then @pages + index - else if index >= @pages then index - @pages - else index + if @loop then index + else Math.max 0, Math.min @pages - 1, index From a0e5c7d8691e59d17dae49491e3c4669bcde5089 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sun, 20 Feb 2022 07:01:47 -0800 Subject: [PATCH 13/23] Making dot clicks work with looping --- src/concerns/pagination.coffee | 13 ++++++++++++- src/ssr-carousel-dots.vue | 4 ++-- src/ssr-carousel.vue | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/concerns/pagination.coffee b/src/concerns/pagination.coffee index 2a168ff..72a0e3d 100644 --- a/src/concerns/pagination.coffee +++ b/src/concerns/pagination.coffee @@ -27,10 +27,16 @@ export default # Get the total number of slides slidesCount: -> @slottedSlides.length + # Apply boundaries to the index, which will exceed them when looping + boundedIndex: -> + if @index < 0 then @pages + @index + else if @index >= @pages then @index - @pages + else @index + watch: # Emit events on index change - index: -> @$emit 'change', { @index } + boundedIndex: -> @$emit 'change', { @boundedIndex } methods: @@ -38,6 +44,11 @@ export default next: -> @goto @index + 1 back: -> @goto @index - 1 + # The dots are ignorant of looping, so convert their bounded index to the + # true index so we don't animate through a ton of pages going to the + # clicked dot. + gotoDot: (dotIndex) -> @goto dotIndex - @boundedIndex + @index + # Go to a specific index goto: (index) -> @index = @applyIndexBoundaries index diff --git a/src/ssr-carousel-dots.vue b/src/ssr-carousel-dots.vue index 041af16..3c54127 100644 --- a/src/ssr-carousel-dots.vue +++ b/src/ssr-carousel-dots.vue @@ -6,7 +6,7 @@ button.ssr-carousel-dot-button( v-for='i in pages' :key='i' :aria-label='`Page ${i}`' - :disabled='index == i - 1' + :disabled='boundedIndex == i - 1' @click='$emit("goto", i - 1)') slot(v-if='$slots.dot' name='dot') span.ssr-carousel-dot-icon(v-else) @@ -19,7 +19,7 @@ export default props: - index: Number + boundedIndex: Number pages: Number diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index 17ab398..f6ae108 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -36,8 +36,8 @@ //- Dots navigation ssr-carousel-dots( v-if='showDots' - v-bind='{ index, pages }' - @goto='goto') + v-bind='{ boundedIndex, pages }' + @goto='gotoDot') template(#dot): slot(name='dot') From fcb025db672391a83907ee3bf181a252ef1a266c Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sun, 20 Feb 2022 07:07:34 -0800 Subject: [PATCH 14/23] Fix drag snapping when dragging left --- src/concerns/dragging.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/concerns/dragging.coffee b/src/concerns/dragging.coffee index d8995b6..e1e3726 100644 --- a/src/concerns/dragging.coffee +++ b/src/concerns/dragging.coffee @@ -45,9 +45,9 @@ export default # direction of the velocity. So that it eases to a stop in the direction # the user was dragging. dragIndex: -> - fractionalIndex = Math.abs if @paginateBySlide - then @currentX / @slideWidth - else @currentX / @pageWidth + fractionalIndex = if @paginateBySlide + then @currentX / @slideWidth * -1 + else @currentX / @pageWidth * -1 switch # If there is very little velocity, go to the closet page From 67cb4496a7062f2981db4817c67bdb165b96b528 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sun, 20 Feb 2022 21:40:31 -0800 Subject: [PATCH 15/23] Moving slottedSlides into the more generic pagination concern --- src/concerns/looping.coffee | 3 --- src/concerns/pagination.coffee | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/concerns/looping.coffee b/src/concerns/looping.coffee index 6c02012..1842934 100644 --- a/src/concerns/looping.coffee +++ b/src/concerns/looping.coffee @@ -22,9 +22,6 @@ export default # Combine slotted slides and clones slides: -> [...@prependedSlides, ...@slottedSlides, ...@appendedSlides] - # Get just the slotted slides that are components, ignoring text nodes - # which may exist as a result of whitespace - slottedSlides: -> @$slots.default.filter (vnode) -> !!vnode.tag methods: diff --git a/src/concerns/pagination.coffee b/src/concerns/pagination.coffee index 72a0e3d..e775591 100644 --- a/src/concerns/pagination.coffee +++ b/src/concerns/pagination.coffee @@ -24,6 +24,10 @@ export default # Disable carousel-ness when there aren't enough slides disabled: -> @slidesCount <= @currentSlidesPerPage + # Get just the slotted slides that are components, ignoring text nodes + # which may exist as a result of whitespace + slottedSlides: -> @$slots.default.filter (vnode) -> !!vnode.tag + # Get the total number of slides slidesCount: -> @slottedSlides.length From dcee7783fbb3f158d23d102bf2acfd5746761c06 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sun, 20 Feb 2022 21:43:47 -0800 Subject: [PATCH 16/23] More stable boundedIndex calculation --- src/concerns/pagination.coffee | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/concerns/pagination.coffee b/src/concerns/pagination.coffee index e775591..9f29b3a 100644 --- a/src/concerns/pagination.coffee +++ b/src/concerns/pagination.coffee @@ -32,10 +32,7 @@ export default slidesCount: -> @slottedSlides.length # Apply boundaries to the index, which will exceed them when looping - boundedIndex: -> - if @index < 0 then @pages + @index - else if @index >= @pages then @index - @pages - else @index + boundedIndex: -> Math.abs(@index) % @pages watch: From a747f36c69e909a130783ddce867b837cca45d36 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sun, 20 Feb 2022 21:44:39 -0800 Subject: [PATCH 17/23] Reorder slides and add track offset to accomplish looping effect --- demo/content/looping.md | 18 ++++++++++++++++++ src/concerns/looping.coffee | 38 ++++++++++++++++++++++++------------- src/ssr-carousel-track.vue | 3 ++- src/ssr-carousel.vue | 2 +- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/demo/content/looping.md b/demo/content/looping.md index e0fdda5..ff22bc2 100644 --- a/demo/content/looping.md +++ b/demo/content/looping.md @@ -18,6 +18,24 @@ title: 'Looping / Inifinte Scroll' ``` +## Looping with multiple slides per page + + + + + + + + +```vue + + + + + + +``` + ## Cloned slides can contain components diff --git a/src/concerns/looping.coffee b/src/concerns/looping.coffee index 1842934..1dc66d5 100644 --- a/src/concerns/looping.coffee +++ b/src/concerns/looping.coffee @@ -4,24 +4,36 @@ Code related to looping / infinite scroll export default # Add prop to enable looping - props: - loop: Boolean + props: loop: Boolean # Store cloned slides - data: -> - prependedSlides: [] - appendedSlides: [] - - # Testing cloneVnode - # created: -> - # clone = @cloneVnode @$slots.default[1] - # @prependedSlides.push clone + data: -> clonedLastSlide: null computed: - # Combine slotted slides and clones - slides: -> [...@prependedSlides, ...@slottedSlides, ...@appendedSlides] - + # Put slides in order, applying rules related to looping + slides: -> + + # If not looping, don't show other slides during boundary dampening + return @slottedSlides unless @loop + + # Breakup the slides into arrays using the modulo of the current + # side index. I came up with this by figuring out how the arrays should + # look and working back from there. + prepended = @slottedSlides.slice @currentSlideIndex % @slidesCount + remainder = @slottedSlides.slice 0, @slidesCount - prepended.length + return [ ...prepended, ...remainder ] + + # This represents the current (as in while scrolling / animating) left most + # slide index. This is used in looping calculation so that the reordering + # of slides isn't affected by paginatePerSlide setting. + currentSlideIndex: -> Math.floor @currentX / @slideWidth * -1 + + # When looping, slides get re-ordered. This value is added to the + # track transform so that the slides don't feel like they were re-ordered. + trackOffset: -> + unless @loop then 0 + else @currentSlideIndex * @slideWidth methods: diff --git a/src/ssr-carousel-track.vue b/src/ssr-carousel-track.vue index b1292b2..0b35b0f 100644 --- a/src/ssr-carousel-track.vue +++ b/src/ssr-carousel-track.vue @@ -9,12 +9,13 @@ export default props: dragging: Boolean currentX: Number + trackOffset: Number slides: Array computed: # Styles that are used to position the track - styles: -> transform: "translateX(#{@currentX}px)" + styles: -> transform: "translateX(#{@currentX + @trackOffset}px)" # Render the track and slotted slides render: (create) -> diff --git a/src/ssr-carousel.vue b/src/ssr-carousel.vue index f6ae108..c22e54c 100644 --- a/src/ssr-carousel.vue +++ b/src/ssr-carousel.vue @@ -21,7 +21,7 @@ ssr-carousel-track( ref='track' :slides='slides' - v-bind='{ dragging, currentX }') + v-bind='{ dragging, currentX, trackOffset }') //- Back / Next navigation ssr-carousel-arrows( From 7be4741a040412978e82dde3747ee059794f7812 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Sun, 20 Feb 2022 22:17:27 -0800 Subject: [PATCH 18/23] Updating vue-visual to prevent flicker when looping --- demo/content/looping.md | 16 ++++------------ demo/package.json | 2 +- demo/yarn.lock | 8 ++++---- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/demo/content/looping.md b/demo/content/looping.md index ff22bc2..d1f07ce 100644 --- a/demo/content/looping.md +++ b/demo/content/looping.md @@ -42,18 +42,14 @@ title: 'Looping / Inifinte Scroll' - - - - @@ -64,18 +60,14 @@ title: 'Looping / Inifinte Scroll' - - - - diff --git a/demo/package.json b/demo/package.json index 5626e41..6202400 100644 --- a/demo/package.json +++ b/demo/package.json @@ -22,6 +22,6 @@ "vue-balance-text": "^1.2.3", "vue-detachable-header": "^0.2.0", "vue-unorphan": "^1.2.3", - "vue-visual": "^2.5.4" + "vue-visual": "^2.6.0" } } diff --git a/demo/yarn.lock b/demo/yarn.lock index c906378..88ad16d 100644 --- a/demo/yarn.lock +++ b/demo/yarn.lock @@ -10574,10 +10574,10 @@ vue-unorphan@^1.2.3: dependencies: unorphan "^1.2.1" -vue-visual@^2.0.0, vue-visual@^2.5.4: - version "2.5.4" - resolved "https://registry.yarnpkg.com/vue-visual/-/vue-visual-2.5.4.tgz#3675bdea3a748bfc56775d88cdeaf27bd0f5e1c2" - integrity sha512-UUMxj0l9vPyR9W28y3g5eel4JsznuBgaqgEm8EhG/Vi2QVhhaDRsTUj0fkN++YcmwXt2iJcpewRDy6ITxQsHjQ== +vue-visual@^2.0.0, vue-visual@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/vue-visual/-/vue-visual-2.6.0.tgz#083c6f83d755d59819db63e10ad249deef4da358" + integrity sha512-clCxWyA8YwjFOUSR+9vXXUomBto4v/+PqP/0DXtsIvOAACnKyDXtKRvHZzTY0EOfNinWZ/7NzTZ0aXgeYhJpVg== vue@^2.6.12: version "2.6.14" From 89e31c95951daf093cc72f90a837d8da87782a87 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Mon, 21 Feb 2022 13:25:11 -0800 Subject: [PATCH 19/23] Improve formatting of p tags in demo site --- demo/pages/_page.vue | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/demo/pages/_page.vue b/demo/pages/_page.vue index f1e51e4..2c3a3bd 100644 --- a/demo/pages/_page.vue +++ b/demo/pages/_page.vue @@ -80,8 +80,7 @@ h1 // Seperate regions on a page h2 - fluid-space margin-top, 'm' - fluid-space margin-bottom, 's' + fluid-space margin-top, 'l' style-h2() // Syntax highlighting @@ -89,9 +88,22 @@ h2 background darken(primary-background, 15%) border 1px solid darken(primary-background, 30%) basic-border-radius() - fluid-space margin-v, 's' + fluid-space margin-bottom, 's' >>> code font-size 14px line-height 1.2 +// Style body text, like notes +p + line-height 1.5 + color lighten(primary-background, 50%) + + // Underline links + a + text-decoration underline + +// Add constant margins around demos +.ssr-carousel + fluid-space margin-v, 's' + From 317eababe3661beef395f697549fbb2bce063e43 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Mon, 21 Feb 2022 13:26:45 -0800 Subject: [PATCH 20/23] Implement filling incomplete pages --- demo/content/looping.md | 6 ++++-- src/concerns/dragging.coffee | 27 ++++++++++++++++----------- src/concerns/pagination.coffee | 25 ++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/demo/content/looping.md b/demo/content/looping.md index d1f07ce..7e7e2c9 100644 --- a/demo/content/looping.md +++ b/demo/content/looping.md @@ -20,11 +20,12 @@ title: 'Looping / Inifinte Scroll' ## Looping with multiple slides per page +Note how the incomplete 2nd page is handled. The 3rd and 1st slide are shown simulataneously. On the next advance forward, the track advances a half width so that the *new* first page contains the 1st and 2nd slide. + - ```vue @@ -32,12 +33,13 @@ title: 'Looping / Inifinte Scroll' - ``` ## Cloned slides can contain components +In this case, we're using [vue-visual](https://github.com/BKWLD/vue-visual) components to render image assets. Note how lazy loading prevents the loading of the second image until you advance forward. + - fractionalIndex = if @paginateBySlide - then @currentX / @slideWidth * -1 - else @currentX / @pageWidth * -1 - switch + dragIndex: -> switch - # If there is very little velocity, go to the closet page - when Math.abs(@dragVelocity) <= 2 then Math.round fractionalIndex + # If there is very little velocity, go to the closet page + when Math.abs(@dragVelocity) <= 2 then Math.round @fractionalIndex - # User was moving forward - when @dragVelocity < 0 then Math.ceil fractionalIndex + # User was moving forward + when @dragVelocity < 0 then Math.ceil @fractionalIndex - # User was moving backward - else Math.floor fractionalIndex + # User was moving backward + else Math.floor @fractionalIndex + + # Determine the current index given the currentX as a fraction. For + # instance, when dragging forward, it will be like 0.1 and when you've + # dragged almost a full page, forward it would be 0.9. + fractionalIndex: -> + x = @currentX - @currentIncompletePageOffset + if @paginateBySlide + then x / @slideWidth * -1 + else x / @pageWidth * -1 # Calculate the width of a slide slideWidth: -> @pageWidth / @currentSlidesPerPage diff --git a/src/concerns/pagination.coffee b/src/concerns/pagination.coffee index 9f29b3a..ae662f4 100644 --- a/src/concerns/pagination.coffee +++ b/src/concerns/pagination.coffee @@ -34,6 +34,9 @@ export default # Apply boundaries to the index, which will exceed them when looping boundedIndex: -> Math.abs(@index) % @pages + # The current incomplete page offset + currentIncompletePageOffset: -> @makeIncompletePageOffset @index + watch: # Emit events on index change @@ -57,12 +60,28 @@ export default # Tween to a specific index tweenToIndex: (index) -> + + # Figure out the new x position x = if @paginateBySlide - then index * @slideWidth - else index * @pageWidth - @targetX = @applyXBoundaries -1 * x + then index * @slideWidth * -1 + else index * @pageWidth * -1 + + # Apply adjustments to x value and persist + x += @makeIncompletePageOffset index + @targetX = @applyXBoundaries x + + # Start tweening @startTweening() + # Creates a px value to represent adjustments that should be made to + # account for incommplete pages of slides when looping is enbaled. Like + # when there is 3 slotted slides and 2 slides per page. + makeIncompletePageOffset: (index) -> + return 0 unless @loop and not @paginateBySlide + Math.floor(index / @pages) * + (@slidesCount % @currentSlidesPerPage) * + @slideWidth + # Apply boundaries to the index applyIndexBoundaries: (index) -> if @loop then index From 2124c19b582089bdc39e72c2d2900d3a081135db Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Mon, 21 Feb 2022 13:41:54 -0800 Subject: [PATCH 21/23] Changing looping title --- demo/content/looping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/content/looping.md b/demo/content/looping.md index 7e7e2c9..da45b07 100644 --- a/demo/content/looping.md +++ b/demo/content/looping.md @@ -1,5 +1,5 @@ --- -title: 'Looping / Inifinte Scroll' +title: 'Looping / Wrap-Around / Infinite Scroll' --- ## Basic looping From cbb77d252f0e00677260c6b2b6ee46f593b9ea48 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Mon, 21 Feb 2022 13:49:43 -0800 Subject: [PATCH 22/23] Remove cloning elements as a concern of looping --- src/concerns/looping.coffee | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/concerns/looping.coffee b/src/concerns/looping.coffee index 1dc66d5..ec1db1c 100644 --- a/src/concerns/looping.coffee +++ b/src/concerns/looping.coffee @@ -6,9 +6,6 @@ export default # Add prop to enable looping props: loop: Boolean - # Store cloned slides - data: -> clonedLastSlide: null - computed: # Put slides in order, applying rules related to looping @@ -34,29 +31,3 @@ export default trackOffset: -> unless @loop then 0 else @currentSlideIndex * @slideWidth - - methods: - - # Clone a vnode, based on - # https://github.com/vuejs/vue/blob/23760b5c7a350484ef1eee18f8c615027a8a8ad9/src/core/vdom/vnode.js#L89 - cloneVnode: (vnode) -> - cloned = new vnode.constructor( - vnode.tag, - vnode.data, - vnode.children && vnode.children.slice(), - vnode.text, - vnode.elm, - vnode.context, - vnode.componentOptions, - vnode.asyncFactory - ) - cloned.ns = vnode.ns - cloned.isStatic = vnode.isStatic - cloned.key = vnode.key - cloned.isComment = vnode.isComment - cloned.fnContext = vnode.fnContext - cloned.fnOptions = vnode.fnOptions - cloned.fnScopeId = vnode.fnScopeId - cloned.asyncMeta = vnode.asyncMeta - cloned.isCloned = true - return cloned From 9ac74d34510da61de3d4a3ec22318ecdfbfdcee7 Mon Sep 17 00:00:00 2001 From: Robert Reinhard Date: Mon, 21 Feb 2022 20:32:21 -0800 Subject: [PATCH 23/23] Adding AKA note to looping docs --- demo/content/looping.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/demo/content/looping.md b/demo/content/looping.md index da45b07..dda2a16 100644 --- a/demo/content/looping.md +++ b/demo/content/looping.md @@ -1,9 +1,11 @@ --- -title: 'Looping / Wrap-Around / Infinite Scroll' +title: 'Looping' --- ## Basic looping +Looping is also known as `wrapAround` or `infinite` in other carousels. +