Multi-item responsive carousel

31,491

Solution 1

ui-bootstrap's carousel is not a good choice, it has other drawback like isolated scope on each slide. I'm using https://github.com/revolunet/angular-carousel which support multi item on each slide.

Because this directive support ng-repeat. You easy change you collection and using nested ng-repeat to set different number of items in each slide.

<ul rn-carousel class="image">
  <li ng-repeat="images in imageCollection">
    <div ng-repeat="image in images" class="layer">{{ image }}</div>
  </li>
</ul>

As you have already defined 3 break points. We just need to reconstruct the imageCollection array when viewport size changed.

$window.on('resize', function() {
    var width = $window.width();
    if(width > 900) {
       // desktop
       rebuildSlide(3);
    } else if(width <= 900 && width > 480) {
       // tablet
       rebuildSlide(2);
    } else {
       // phone
       rebuildSlide(1);
    }
    // don't forget manually trigger $digest()
    $scope.$digest();
});

function rebuildSlide(n) {
   var imageCollection = [],
       slide = [],
       index;
   // values is your actual data collection.
   for(index = 0; index < values.length; index++) {
       if(slide.length === n) {
           imageCollection.push(slide);
           slide = [];
       }
       slide.push(values[index]);
   }
   imageCollection.push(slide);
   $scope.imageCollection = imageCollection;
}

Solution 2

So, I tried this one so as to make angularjs Carousel (ui.bootstrap.carousel) to work with multi items per animation. I have also tried to apply [Detection for Responsive Websites using AngularJS].2

Take a look here: http://plnkr.co/edit/QhBQpG2nCAnfsb9mpTvj?p=preview

Results:

1 ) One Item (Mobile Version) :

enter image description here

2 ) Two Items (Tablet Version) :

enter image description here

3 ) Three Items (Desktop Version) :

enter image description here

PART 2: It can also detect the resolution of the window so as to determine if it is tablet,mobile or desktop following this tutorial... Try to use this values: "mobile, tablet, desktop" to see the three different view versions.

Demonstration of the tablet version:

var app = angular.module('myApp', ['ui.bootstrap', 'angular-responsive']);

app.controller('MainCtrl', function($scope) {
  $scope.displayMode = 'mobile'; // default value


  $scope.$watch('displayMode', function(value) {

    switch (value) {
      case 'mobile':
        // do stuff for mobile mode
          console.log(value);
        break;
      case 'tablet':
        // do stuff for tablet mode
          console.log(value);
        break;
    }
  });
});

function CarouselDemoCtrl($scope) {
  var whatDevice = $scope.nowDevice;
  $scope.myInterval = 7000;
  $scope.slides = [{
    image: 'http://placekitten.com/221/200',
    text: 'Kitten.'
  }, {
    image: 'http://placekitten.com/241/200',
    text: 'Kitty!'
  }, {
    image: 'http://placekitten.com/223/200',
    text: 'Cat.'
  }, {
    image: 'http://placekitten.com/224/200',
    text: 'Feline!'
  }, {
    image: 'http://placekitten.com/225/200',
    text: 'Cat.'
  }, {
    image: 'http://placekitten.com/226/200',
    text: 'Feline!'
  }, {
    image: 'http://placekitten.com/227/200',
    text: 'Cat.'
  }, {
    image: 'http://placekitten.com/228/200',
    text: 'Feline!'
  }, {
    image: 'http://placekitten.com/229/200',
    text: 'Cat.'
  }, {
    image: 'http://placekitten.com/230/200',
    text: 'Feline!'
  }];


    var i, first = [],
      second, third;
    var many = 1;

    //##################################################    
    //Need to be changed to update the carousel since the resolution changed
    $scope.displayMode = "tablet";
    //##################################################
    if ($scope.displayMode == "mobile") {many = 1;}
    else if ($scope.displayMode == "tablet") {many = 2;} 
    else {many = 3;}

    for (i = 0; i < $scope.slides.length; i += many) {
      second = {
        image1: $scope.slides[i]
      };
      if (many == 1) {}
      if ($scope.slides[i + 1] && (many == 2 || many == 3)) {
        second.image2 = $scope.slides[i + 1];

      }
      if ($scope.slides[i + (many - 1)] && many == 3) {
        second.image3 = $scope.slides[i + 2];
      }
      first.push(second);
    }
    $scope.groupedSlides = first;
}

app.directive('dnDisplayMode', function($window) {
  return {
    restrict: 'A',
    scope: {
      dnDisplayMode: '='
    },
    template: '<span class="mobile"></span><span class="tablet"></span><span class="tablet-landscape"></span><span class="desktop"></span>',
    link: function(scope, elem, attrs) {
      var markers = elem.find('span');

      function isVisible(element) {
        return element && element.style.display != 'none' && element.offsetWidth && element.offsetHeight;
      }

      function update() {
        angular.forEach(markers, function(element) {
          if (isVisible(element)) {
            scope.dnDisplayMode = element.className;
            return false;
          }
        });
      }

      var t;
      angular.element($window).bind('resize', function() {
        clearTimeout(t);
        t = setTimeout(function() {
          update();
          scope.$apply();
        }, 300);
      });

      update();
    }
  };
});

Hope it helps!

Share:
31,491

Related videos on Youtube

Katana24
Author by

Katana24

Working with Android and Angular.js...

Updated on July 09, 2022

Comments

  • Katana24
    Katana24 almost 2 years

    I'm building a website that requires a carousel to be implemented. Because this website is built on AngularJS I wanted to go with Angulars Boostrap Carousel, however, this carousel appears to only allow one image at a time.

    What I will need will be 3 images at a time on desktop, on a tablet 2 images and on mobile 1. So there's a significant element of responsive design involved here too.

    Does anyone have any experince with this that doesn't involve JQuery? I'm not opposed to it but have been told by a senior member of the team to try to source an alternative, if any.

    What I tried from Angulars bootstrap:

       $scope.getPromoURLs = function() {
            var subObj = myJSON.response.details.promotionalSpots;
            for( var keys in subObj ) {
                var value = subObj[keys].promotionUrl;
                $scope.slides.push( value );
            }
        };
        // Builts an array of promotional URLS to from a JSON object to source the images
        $scope.getPromoURLs();
    
        $scope.addSlide = function () {
            // Test to determine if 3 images can be pulled together - FAILS
            var newWidth = 600 + slides.length;
            slides.push({
               image: ''+slides[0]+''+slides[1] // etc
               // Tried to stitch images together here 
            });
        };
    
        // TODO Should examine array length not hardcoded 4
        for (var i = 0; i < 4; i++) {
            $scope.addSlide();
        }        
    
    • GregL
      GregL over 9 years
      Should I use a carousel? (Spoiler: the answer is no). Is a carousel really, really necessary?
    • Katana24
      Katana24 over 9 years
      @GregL Hi Greg, yeah I've read that before and unfortunately its a requirement from the business and has already been questioned by developers - they're sticking with it
    • yunzen
      yunzen over 9 years
      You may have a look at github.com/gilbitron/carouFredSel. It's a responsive carousel (alas built on top of jQuery)
    • Christina
      Christina over 9 years
      @Katana24 -- I use owlgraphic.com/owlcarousel/demos/itemsCustom.html (this is version 1 of this carousel, version 2 is better but in Beta and I would not use in production).
  • Katana24
    Katana24 over 9 years
    I'm currently in the process of examining this but from what I've seen it should do the job. The key part of the functonality that I want is that I shouldn't be loading any extra JQuery libraries. Good find!
  • Sampath
    Sampath over 9 years
    What do you mean by multi items ? Can we do like this by using above directive ? bootsnipp.com/snippets/featured/carousel-product-cart-slider
  • Bob Yuan
    Bob Yuan over 9 years
    @Sampath multi items means you need to use ng-repeat to generate multiple block inside each slide. your show case can be supported by this directive
  • Ravul
    Ravul over 8 years
    @lordfriend how would you do it with 3 items, but when you swipe, only an item hides from one side while only one item appears from the other side? like this: coolcarousels.frebsite.nl/c/58
  • Bob Yuan
    Bob Yuan over 8 years
    @Ravul Well, the feature you expected may be not supported by the directive. you may have to find another solution
  • Beslinda N.
    Beslinda N. almost 8 years
    Is this code broken. When I check the demo, on smaller screen the slide is still there, it is just shown vertically ?
  • Ajay Barot
    Ajay Barot over 7 years
    Can we do this dynamically ? I want to create this type of carousel. carousel