diff --git a/demo/components/demos/responsive/variable-width-with-arrows.vue b/demo/components/demos/responsive/variable-width-with-arrows.vue new file mode 100644 index 0000000..6c30aa8 --- /dev/null +++ b/demo/components/demos/responsive/variable-width-with-arrows.vue @@ -0,0 +1,13 @@ + diff --git a/demo/content/responsive.md b/demo/content/responsive.md index 2b6c8d1..140f2a4 100644 --- a/demo/content/responsive.md +++ b/demo/content/responsive.md @@ -70,7 +70,10 @@ While it's not the primary use case of this package, you if you set `slidesPerPa - If there are not enough slides to fill the viewport, slides will be left aligned rather than center aligned. - This hasn't been tested with responsive props or looping. Peeking doesn't make sense for this use case but care hasn't been taken to disabling it. -- Pagination controls aren't supported yet, this is purely drag only. +- Pagination controls are in beta + - Pagination is done on a per slide basis + - Looping still has not been implemented + - Slides are left aligned @@ -82,6 +85,24 @@ While it's not the primary use case of this package, you if you set `slidesPerPa ``` +Carousel with variable width and arrows: + + + +```vue + + + + + + + + + + + +``` + Here's an example where there aren't enough slides to exceed the carouel width: diff --git a/src/concerns/dimensions.coffee b/src/concerns/dimensions.coffee index 3258b42..b06713c 100644 --- a/src/concerns/dimensions.coffee +++ b/src/concerns/dimensions.coffee @@ -80,7 +80,7 @@ export default @carouselWidth = @$el.getBoundingClientRect().width + @gutterWidth @viewportWidth = window.innerWidth @capturePeekingMeasurements() - @captureTrackWidth() if @isVariableWidth + @captureCarouselDims() if @isVariableWidth # Make the width style that gives a slide it's width given # slidesPerPage. Reduce this width by the gutter if present @@ -114,3 +114,10 @@ export default (#{@autoUnit(peekLeft)} + #{@autoUnit(peekRight)}) / #{slidesPerPage} - (#{@autoUnit(gutter)} * #{slidesPerPage - 1}) / #{slidesPerPage} )" + + + # Get the target X scroll position of a given slide + targetXOfIdx: (idx) -> + if @isVariableWidth + then @measuredSlidesWidths[idx].targetXScroll + else @pageWidth / @currentSlidesPerPage diff --git a/src/concerns/dragging.coffee b/src/concerns/dragging.coffee index 67614d7..4ebd3bb 100644 --- a/src/concerns/dragging.coffee +++ b/src/concerns/dragging.coffee @@ -73,6 +73,8 @@ export default fractionalIndex: -> return 0 unless @trackWidth + if @isVariableWidth then return @fractionalIndexFromMeasurements + # Work in positive numbers x = @currentX * -1 @@ -104,6 +106,16 @@ export default # Return the final value by adding all the passed index values return pageProgressPercent + setIndex * @pages + pageIndex + fractionalIndexFromMeasurements: -> + # Work in positive numbers + x = @currentX * -1 + + slideIdx = @measuredSlidesWidths.findIndex((measuredSlide) => measuredSlide.targetXScroll > x) - 1 + + percentage = (x - @measuredSlidesWidths[slideIdx].targetXScroll) / @measuredSlidesWidths[slideIdx].width + + return slideIdx + percentage + # Determine if the user is dragging vertically isVerticalDrag: -> return unless @dragDirectionRatio @@ -141,7 +153,7 @@ export default else @gotoEnd() # If rendering variable width slides, don't come to a rest at an index - else if @isVariableWidth then @tweenToStop() + else if @isVariableWidth then @goto @dragIndex # If user was vertically dragging, reset the index else if @isVerticalDrag then @goto @index diff --git a/src/concerns/pagination.coffee b/src/concerns/pagination.coffee index 5b2d268..fe86a10 100644 --- a/src/concerns/pagination.coffee +++ b/src/concerns/pagination.coffee @@ -22,6 +22,8 @@ export default # The current number of pages pages: -> switch + # When variable width, pages is slide count + when @isVariableWidth then @slidesCount # When looping and paginating per slide, make a dot per slide when @paginateBySlide and @shouldLoop then @slidesCount @@ -146,9 +148,10 @@ export default getXForIndex: (index) -> # Figure out the new x position - x = if @paginateBySlide - then index * @slideWidth * -1 - else index * @pageWidth * -1 + x = switch + when @isVariableWidth then @targetXOfIdx(@applyIndexBoundaries(index)) * -1 + when @paginateBySlide then index * @slideWidth * -1 + else index * @pageWidth * -1 # Apply adjustments to x value and persist x += @makeIncompletePageOffset index diff --git a/src/concerns/variable-width.coffee b/src/concerns/variable-width.coffee index 011f741..971031c 100644 --- a/src/concerns/variable-width.coffee +++ b/src/concerns/variable-width.coffee @@ -3,7 +3,9 @@ Functionality related to supporting variable width slides ### export default - data: -> measuredTrackWidth: 0 + data: -> + measuredTrackWidth: 0 + measuredSlidesWidths: [] computed: @@ -11,8 +13,26 @@ export default isVariableWidth: -> @slidesPerPage == null methods: + # Capture all dimensions of carousel + captureCarouselDims: -> + @captureTrackWidth() + @captureSlideWidths() # Measure the width of the track captureTrackWidth: -> return unless @$refs.track @measuredTrackWidth = @$refs.track.$el.scrollWidth + + # Capture slide dims and place them into an array of data + captureSlideWidths: -> + return unless @$refs.track + @measuredSlidesWidths = @$refs?.track?.$children.reduce((acc, child, idx, arr) => + return [ + ...acc + { + width: child.$el.clientWidth + targetXScroll: (acc[idx - 1]?.targetXScroll || 0) + (acc[idx - 1]?.width || 0) + @gutter * (idx > 0) + } + ] + , [] ) +