Created
September 6, 2018 16:00
-
-
Save kevinboudot/cba61d1663fe3516bcd2f05dbf7465b9 to your computer and use it in GitHub Desktop.
https://durimel.io/nel Carousel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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