Skip to content

Instantly share code, notes, and snippets.

@kevinboudot
Created September 6, 2018 16:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevinboudot/cba61d1663fe3516bcd2f05dbf7465b9 to your computer and use it in GitHub Desktop.
Save kevinboudot/cba61d1663fe3516bcd2f05dbf7465b9 to your computer and use it in GitHub Desktop.
import EventEmitter from 'framework/core/eventEmitter';
import Easer from 'framework/tools/easer';
import Resizer from 'framework/tools/resizer';
import Scroller from 'framework/tools/scroller';
import MathUtils from 'framework/utils/math';
import {
$
} from 'framework/tools/selector';
class Carousel extends EventEmitter {
constructor( options ) {
super( options );
this.lines = options.lines || 3;
this.skewReducer = options.skewReducer || 30;
this.skewLimit = options.skewLimit || 30;
this.$ = {};
this.$.body = $( document.body );
this.$.list = options.list;
this.$.projects = this.$.list.find( 'li' );
this.scroller = new Scroller( {
isNegative: true,
horiz: true
} );
this.resizer = new Resizer();
this.easer = new Easer( {
ease: 0.06,
easeLimit: 0.1
} );
this.sizes = {};
this.projects = [];
this.stillScrolled = false;
this.isReady = false;
this.isDisable = false;
this.sizes.lineWidth = [];
this.projectsByLine = [];
this.currentDirection = null;
this.createLines();
this.observe();
let _this = this;
window.setTimeout( function() {
_this.start();
}, 300 );
}
start() {
let _this = this;
this.$.scrollTo = this.$.body.find( '.common-footer .scrollto' );
this.$.list.addClass( 'shown' );
this.scroller.fakeScrollY = -this.sizes.w * .29;
this.scroller.trigger( 'mousewheel', {
top: this.scroller.fakeScrollY,
direction: 'down'
} );
this.scroller.block();
window.setTimeout( function() {
_this.isReady = true;
_this.easer.ease = 0.1;
_this.scroller.unblock();
}, 1400 );
}
hide() {
}
createLines() {
let _this = this;
let fullProjects = [];
let lineItemsCount = [];
this.linkMouseEnterHandler = this.linkMouseEnterHandler.bind( this );
this.linkMouseLeaveHandler = this.linkMouseLeaveHandler.bind( this );
this.linkClickHandler = this.linkClickHandler.bind( this );
this.$.projects.each( function( el, i, l ) {
let line = Math.ceil( ( i + 1 ) / Math.ceil( l / _this.lines ) ) - 1;
lineItemsCount[ line ] = lineItemsCount[ line ] !== undefined ? lineItemsCount[ line ] + 1 : 0;
let project = {
el: el,
index: i,
line: line,
lineIndex: lineItemsCount[ line ]
};
el.addClass( 'line-' + line );
el.on( 'mouseenter', _this.linkMouseEnterHandler );
el.on( 'mouseleave', _this.linkMouseLeaveHandler );
el.on( 'click', _this.linkClickHandler );
fullProjects[ i ] = project;
_this.projectsByLine[ line ] = _this.projectsByLine[ line ] || [];
_this.projectsByLine[ line ].push( project );
} );
this.projects = fullProjects;
}
linkClickHandler( e ) {
let btn = $( e.currentTarget );
btn.removeClass( 'hovered' );
this.trigger( 'click' );
//this.$.body.removeClass('project-hovered');
}
linkMouseEnterHandler( e ) {
let btn = $( e.currentTarget );
let color = btn.attr( 'data-color' );
btn.addClass( 'hovered' );
this.trigger( 'mouseenter', {
e: e,
color: color
} );
//this.$.body.addClass('project-hovered');
}
linkMouseLeaveHandler( e ) {
let btn = $( e.currentTarget );
btn.removeClass( 'hovered' );
this.trigger( 'mouseleave', {
e: e
} );
//this.$.body.removeClass('project-hovered');
}
observe() {
this.resizeHandler = this.resizeHandler.bind( this );
this.resizer.on( 'resize', this.resizeHandler );
this.scrollHandler = this.scrollHandler.bind( this );
this.scroller.on( 'mousewheel', this.scrollHandler );
this.easeHandler = this.easeHandler.bind( this );
this.easer.on( 'frame', this.easeHandler );
}
resizeHandler( infos ) {
let _this = this;
this.sizes.h = infos.height;
this.sizes.w = infos.width;
this.sizes.lineWidth = [];
let i = this.projectsByLine.length;
while ( i-- ) {
let line = i;
let projects = this.projectsByLine[ i ];
let j = projects.length;
let lineWidth = 0;
while ( j-- ) {
let project = projects[ j ];
let sizes = project.el.sizes();
let leftPos = 0;
let topPos = ( ( ( this.sizes.h / 2 ) - ( ( this.lines * sizes.height ) / 2 ) ) + ( sizes.height * i ) );
// set length by line
project.byLine = projects.length;
// get Left pos
let k = projects.length;
while ( k-- ) {
let prevProject = projects[ k ];
if ( j > k ) {
leftPos += prevProject.el.sizes().width;
}
}
// add el width for line width
this.sizes.lineWidth[ i ] = this.sizes.lineWidth[ i ] ? this.sizes.lineWidth[ i ] + sizes.width : sizes.width;
// place element
project.el.removeAttr( 'style' );
project.el.css( {
left: leftPos + 'px',
top: topPos + 'px'
} );
// save values
project.sizes = {};
project.sizes.w = sizes.width;
project.pos = {};
project.pos.left = leftPos;
project.pos.top = topPos;
}
}
}
scrollHandler( infos ) {
if ( !this.isDisable ) {
if ( this.isReady ) {
if ( !this.stillScrolled ) {
this.stillScrolled = true;
this.$.scrollTo.addClass( 'scrolled' );
}
}
this.trigger( 'scroll' );
this.easer.set( {
y: infos.top * 0.5
} );
}
}
easeHandler( infos ) {
let posY = -infos.pos.y;
let skewY = MathUtils.clamp( infos.waste.y / this.skewReducer, -this.skewLimit, this.skewLimit );
let i = this.projects.length;
this.currentDirection = infos.direction.y;
while ( i-- ) {
let project = this.projects[ i ];
let line = project.line;
let isOddLine = line % 2 === 1;
// delayed positions and skews
project.speed = 1 - ( ( line / this.lines ) / 2 );
if ( project.pos ) {
project.pos.x = isOddLine ? -posY * project.speed : posY * project.speed;
}
project.skew = isOddLine ? -skewY * project.speed : skewY * project.speed;
if ( project.pos ) {
if ( ( project.pos.left + project.pos.x + project.sizes.w ) < 0 ) {
project.isBefore = isOddLine ? false : true;
project.isAfter = isOddLine ? true : false;
} else if ( ( project.pos.left + project.pos.x ) > this.sizes.w ) {
project.isBefore = isOddLine ? true : false;
project.isAfter = isOddLine ? false : true;
} else {
project.isBefore = false;
project.isAfter = false;
}
}
// animate lines
if ( project.pos ) {
project.el.css( {
transform: 'skewX(' + project.skew + 'deg) translate3d(' + project.pos.x + 'px, 0, 0)'
} );
}
// set Infinite
this.setInfinite();
}
}
setInfinite() {
let i = this.projectsByLine.length;
while ( i-- ) {
let line = i;
let projects = this.projectsByLine[ i ];
let lineWidth = this.sizes.lineWidth[ line ];
let isOddLine = line % 2 === 1;
let j = projects.length;
while ( j-- ) {
let project = projects[ j ];
if ( this.currentDirection === 'down' && project.isAfter ) {
let left = isOddLine ? ( project.pos.left + lineWidth ) : project.pos.left - lineWidth;
project.isBefore = true;
project.isAfter = false;
project.el.css( {
left: left + 'px'
} );
project.pos.left = left;
}
if ( this.currentDirection === 'up' && project.isBefore ) {
let left = isOddLine ? ( project.pos.left - lineWidth ) : project.pos.left + lineWidth;
project.isBefore = false;
project.isAfter = true;
project.el.css( {
left: left + 'px'
} );
project.pos.left = left;
}
}
}
}
destroy() {
this.resizer.off( 'resize', this.resizeHandler );
this.resizer.destroy();
this.scroller.off( 'mousewheel', this.scrollHandler );
this.scroller.destroy();
this.easer.off( 'frame', this.easeHandler );
this.easer.destroy();
}
}
export default Carousel;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment