March 30, 2015

Carousel (Slide Show) module for famo.us

Slide Show module is written in javaScript using famo.us framework.
The module is a modification of 'sliderShow' module for famo.us.
demo of non-modified version (Note: This demo works on old version of famo.us)

List of changes:
1) fixed bug with using old version of famo.us (otherwise doesn't work at all).
2) fixed bug: instead of Modifier use StateModifier.
3) changed CSS.
4) changed constructor feed parameters.
5) adjustable nav. bubble radius.
6) solved positioning bug for bubbles.
7) fixed translation bug: using translate(x, y,0.01) instead of translate(x,y,0).
8) adjustable size of the sliderShow container.


var slideshow = new Slidershow({
   width: window.innerWidth,
   height: 500,
   transition: {duration: 600, curve: 'easeInOut' },
   navDotRadius: window.innerWidth/100,
   navDotGap: window.innerWidth / 75,
   sliders: renderablesToShow
});

GISTS (modified version):
slidershow,
css

define(function (require, exports, module) {
 'use strict';

 var Surface = require('famous/core/Surface');
 var StateModifier = require('famous/modifiers/stateModifier');
 var Transform = require('famous/core/Transform');
 var EventHandler = require('famous/core/EventHandler');
 var OptionsManager = require('famous/core/OptionsManager');
 var View = require('famous/core/View');
 var ContainerSurface = require('famous/surfaces/ContainerSurface');
 var Utility = require('famous/utilities/Utility');

 function Slidershow(options) {
  this.options = Object.create(Slidershow.DEFAULT_OPTIONS);
  this._optionsManager = new OptionsManager(this.options);

  if (options) this.setOptions(options);

  this.total = this.options.sliders.length;
  this.page = 1;
  this._sliders = [];
  this._rwdDelay = undefined;
  this._currentSlideId = 0;
  this._navigationSurf = [];

  this._eventOutput = new EventHandler();
  EventHandler.setOutputHandler(this, this._eventOutput);

  _createSlider.call(this);
 }

 Slidershow.DEFAULT_OPTIONS = {
  width: window.innerWidth,
  height: 500,
  transition: {
   duration: 600,
   curve: 'easeInOut'
  },
  navDotRadius: window.innerWidth/100,
  navDotGap: window.innerWidth / 75
 };

 function _createSlider() {
  this.container = new ContainerSurface({
   size: [(this.options.width === window.innerWidth ? undefined : this.options.width), this.options.height],
   properties: {
    overflow: 'hidden',
    backgroundColor: 'rgb(33, 33, 33)'
   }
  });

  this.sliderContainer = new ContainerSurface({
   size: [(this.options.width === window.innerWidth ? undefined : this.options.width), this.options.height],
   properties: {
    overflow: 'hidden'
   }
  });

  // Create slide items
  _createSlideItem.call(this);

  // Navigation
  if (this.total > 1) _createNavigation.call(this);

  this.container.add(this.sliderContainer);

  if (this.options.width === window.innerWidth) {
   window.addEventListener('resize', function () {
    this.options.width = window.innerWidth;
   }.bind(this), false);
  }
 }

 function _createNavButton(direction) {     // Prev, Next button
  var container, surf, mod;

  container = new ContainerSurface({
   size: [true, undefined],
   properties: {
    background: 'rgba(33,33,33,0.4)',
    padding: '2em'
   }
  });
  surf = new Surface({
   size: [true, true],
   content: '',
   classes: ['projects-assets-nav-button']
  });
  mod = new StateModifier({
   align: [0.5, 0.5],
   origin: [0.5, 0.5]
  });
  container.add(mod).add(surf);

  mod = new StateModifier({
   align: [(direction === 'prev' ? 0 : 1), 0.5],
   origin: [(direction === 'prev' ? 0 : 1), 0.5]
  });

  container.on('click', function (e) {
   this.slidingPage(direction);
  }.bind(this));

  this.container.add(mod).add(container);
 }

 function _createNavBubble(bubble, view) {
  var surf, mod;

  surf = new Surface({
   classes: ['projects-assets-bubble-button'],
   properties: {
    borderWidth: this.options.navDotRadius + 'px',
    borderRadius: bubble === 0 ? 2 * this.options.navDotRadius + 'px' : this.options.navDotRadius + 'px',
    padding: bubble === 0 ? this.options.navDotRadius + 'px' : '0px'
   }
  });

  var dist = (bubble != 0) ? bubble * (this.options.navDotRadius * 2 + this.options.navDotGap) - this.options.navDotRadius : -2 * this.options.navDotRadius;

  mod = new StateModifier({
   size: (bubble === 0 ? [this.options.navDotRadius * 3, this.options.navDotRadius * 3] : [this.options.navDotRadius, this.options.navDotRadius]),
   transform: Transform.translate(dist, 0, 0.01),
   origin: [0, 0.5]
  });
  view._add(mod).add(surf);

  surf.on('click', function (e) {
   this.jumpToSlide(bubble);
  }.bind(this));

  this._navigationSurf.push({ view: view, surf: surf });
 }

 function _createNavigation() {
  var surf, mod, container, view, i;

  _createNavButton.call(this, 'prev');
  _createNavButton.call(this, 'next');

  container = new ContainerSurface({
   size: [(this.total - 1) * (this.options.navDotGap + 2 * this.options.navDotRadius), this.options.navDotRadius]
  });

  view = new View();
  for (i = 0; i < this.total; i++) {
   _createNavBubble.call(this, i, view);
  }
  container.add(view);

  mod = new StateModifier({
   origin: [0.5, 0.5],
   align: [0.5, 0.9]
  });

  this.container.add(mod).add(container);
 }

 function _createSlideItem() {
  for (var i = (this.total - 1) ; i >= 0; i--) {

   var container = new ContainerSurface({ size: [this.options.width, this.options.height] });

   if (typeof this.options.sliders[i] === 'object') container.add(this.options.sliders[i]);

   var view = new View({});

   var dx; // calculate nitial x position of the slide
   if (i === 0) { //first item
    dx = 0;
   } else {
    if (i === 1) { //next item
     dx = this.options.width;
    } else if (i === this.total - 1) { // prev item
     dx = -this.options.width;
    } else {
     dx = -10 * this.options.width; //all other items
    }
   }

   view.add(new StateModifier({
    transform: Transform.translate(dx, 0, 0.01)
   })).add(container);

   this._sliders.push(view);
   this.sliderContainer.add(view);
  }
 }

 function _resetNavigation(slideId) {
  var activated = {
   borderRadius: 2 * this.options.navDotRadius + 'px',
   padding: this.options.navDotRadius + 'px'
  }
  var deactivated = {
   borderRadius: this.options.navDotRadius + 'px',
   padding: '0px'
  }
  var nav = this._navigationSurf[this._currentSlideId];
  nav.surf.setOptions({ properties: deactivated });
  nav.view._node._child[this._currentSlideId].get().setSize([this.options.navDotRadius, this.options.navDotRadius]);
  var dist = this._currentSlideId * (this.options.navDotRadius * 2 + this.options.navDotGap) - this.options.navDotRadius;
  nav.view._node._child[this._currentSlideId].get().setTransform(Transform.translate(dist, 0, 0.01));
  nav.view._node._child[this._currentSlideId].get().setOrigin([0, 0.5]);

  nav = this._navigationSurf[slideId];
  nav.surf.setOptions({ properties: activated });
  nav.view._node._child[slideId].get().setSize([this.options.navDotRadius * 3, this.options.navDotRadius * 3]);
  var dist = slideId * (this.options.navDotRadius * 2 + this.options.navDotGap) - 2 * this.options.navDotRadius;
  nav.view._node._child[slideId].get().setTransform(Transform.translate(dist, 0, 0.01));
  nav.view._node._child[slideId].get().setOrigin([0, 0.5]);

  this._currentSlideId = slideId;
 }

 Slidershow.prototype.getTotal = function getTotal() {
  return this.total;
 };

 Slidershow.prototype.getPage = function getPage() {
  return this.page;
 };

 Slidershow.prototype.jumpToSlide = function jumpToSlide(slide, direction /* only for prev, next */) {
  var current = this.total - this.page >= this.total ?
      this.total - 1 : this.total - this.page <= 0 ?
      0 : this.total - this.page,
   next = current - 1 < 0 ? this.total - 1 : current - 1,
   prev = current + 1 >= this.total ? 0 : current + 1,
   feature = this.total - (slide + 1);

  if (current === feature) return true;
  var direction = direction || 'feature';

  _resetNavigation.call(this, slide);

  if (Math.abs(current - feature) !== (this.total - 1)) {
   this._sliders[next]._node.get().setTransform(
     Transform.translate(this.options.width * -10, 0, 0.01),
     undefined
   );
   this._sliders[prev]._node.get().setTransform(
     Transform.translate(this.options.width * -10, 0, 0.01),
     undefined
   );
  }

  this._sliders[feature]._node.get().setTransform(
    Transform.translate(this.options.width * (current > feature ? 1 : -1), 0, 0.01)
  );
  this._sliders[feature]._node.get().setTransform(
    Transform.translate(0, 0, 0.01),
    this.options.transition
  );
  this._sliders[current]._node.get().setTransform(
    Transform.translate(this.options.width * (current > feature ? -1 : 1), 0, 0.01),
    this.options.transition
  );

  if (Math.abs(current - feature) !== (this.total - 1)) {
   next = feature - 1 < 0 ? this.total - 1 : feature - 1;
   prev = feature + 1 >= this.total ? 0 : feature + 1;

   if (current > feature) {
    this._sliders[next]._node.get().setTransform(
      Transform.translate(this.options.width, 0, 0.01),
      undefined
    );
   } else {
    this._sliders[prev]._node.get().setTransform(
      Transform.translate(this.options.width * -1, 0, 0.01),
      undefined
    );
   }
  }

  this.page = slide + 1;
  this.page = (this.page > this.total) ? 1 : (this.page < 1) ? this.total : this.page;

  this._eventOutput.emit('pageChange', { page: this.page, direction: direction });
 };

 Slidershow.prototype.slidingPage = function slidingPage(direction) {
  if (direction === 'next') {
   this.jumpToSlide((this.page >= this.total) ? 0 : this.page, direction);
  } else if (direction === 'prev') {
   this.jumpToSlide((this.page <= 1) ? this.total - 1 : this.page - 2, direction);
  }
 };

 Slidershow.prototype.setOptions = function setOptions(options) {
  if (options.sliders === undefined || options.sliders.length === 0) {
   options.sliders = [];
  }
  if (options.width === undefined || typeof options.width !== 'number') {
   options.width = window.innerWidth;
  }
  if (options.height === undefined || typeof options.height !== 'number') {
   options.height = 500;
  }
  if (options.transition === undefined || typeof options.transition !== 'object') {
   options.transition = {
    duration: 600,
    curve: 'easeInOut'
   };
  }

  this._optionsManager.setOptions(options);
 };

 Slidershow.prototype.render = function render() {
  if (this.total === 0) return null;

  return [
    {
     target: this.container.render()
    }
  ];
 };

 module.exports = Slidershow;
});
CSS:

.projects-assets-nav-button {
 text-align: center;
 color: rgba(255,255,255,0.8);
 cursor: pointer;
 font-size: 4em;
 line-height: 1em;
}

.projects-assets-nav-button:hover {
 color: rgb(252, 236, 60);
}
 
.projects-assets-bubble-button {
 border-color: rgba(252, 236, 60, 0.8);
 cursor: pointer;
 box-shadow: 10px 6px 35px 0px rgb(33, 33, 33);
 border-style: solid;
}

.projects-assets-bubble-button:hover {
 border-color: rgb(252, 236, 60);
}

No comments:

Post a Comment