UNPKG

iscroll

Version:

Smooth scrolling for the web

248 lines (198 loc) 5.06 kB
_initSnap: function () { this.currentPage = {}; if ( typeof this.options.snap == 'string' ) { this.options.snap = this.scroller.querySelectorAll(this.options.snap); } this.on('refresh', function () { var i = 0, l, m = 0, n, cx, cy, x = 0, y, stepX = this.options.snapStepX || this.wrapperWidth, stepY = this.options.snapStepY || this.wrapperHeight, el; this.pages = []; if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { return; } if ( this.options.snap === true ) { cx = Math.round( stepX / 2 ); cy = Math.round( stepY / 2 ); while ( x > -this.scrollerWidth ) { this.pages[i] = []; l = 0; y = 0; while ( y > -this.scrollerHeight ) { this.pages[i][l] = { x: Math.max(x, this.maxScrollX), y: Math.max(y, this.maxScrollY), width: stepX, height: stepY, cx: x - cx, cy: y - cy }; y -= stepY; l++; } x -= stepX; i++; } } else { el = this.options.snap; l = el.length; n = -1; for ( ; i < l; i++ ) { if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { m = 0; n++; } if ( !this.pages[m] ) { this.pages[m] = []; } x = Math.max(-el[i].offsetLeft, this.maxScrollX); y = Math.max(-el[i].offsetTop, this.maxScrollY); cx = x - Math.round(el[i].offsetWidth / 2); cy = y - Math.round(el[i].offsetHeight / 2); this.pages[m][n] = { x: x, y: y, width: el[i].offsetWidth, height: el[i].offsetHeight, cx: cx, cy: cy }; if ( x > this.maxScrollX ) { m++; } } } this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); // Update snap threshold if needed if ( this.options.snapThreshold % 1 === 0 ) { this.snapThresholdX = this.options.snapThreshold; this.snapThresholdY = this.options.snapThreshold; } else { this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); } }); this.on('flick', function () { var time = this.options.snapSpeed || Math.max( Math.max( Math.min(Math.abs(this.x - this.startX), 1000), Math.min(Math.abs(this.y - this.startY), 1000) ), 300); this.goToPage( this.currentPage.pageX + this.directionX, this.currentPage.pageY + this.directionY, time ); }); }, _nearestSnap: function (x, y) { if ( !this.pages.length ) { return { x: 0, y: 0, pageX: 0, pageY: 0 }; } var i = 0, l = this.pages.length, m = 0; // Check if we exceeded the snap threshold if ( Math.abs(x - this.absStartX) < this.snapThresholdX && Math.abs(y - this.absStartY) < this.snapThresholdY ) { return this.currentPage; } if ( x > 0 ) { x = 0; } else if ( x < this.maxScrollX ) { x = this.maxScrollX; } if ( y > 0 ) { y = 0; } else if ( y < this.maxScrollY ) { y = this.maxScrollY; } for ( ; i < l; i++ ) { if ( x >= this.pages[i][0].cx ) { x = this.pages[i][0].x; break; } } l = this.pages[i].length; for ( ; m < l; m++ ) { if ( y >= this.pages[0][m].cy ) { y = this.pages[0][m].y; break; } } if ( i == this.currentPage.pageX ) { i += this.directionX; if ( i < 0 ) { i = 0; } else if ( i >= this.pages.length ) { i = this.pages.length - 1; } x = this.pages[i][0].x; } if ( m == this.currentPage.pageY ) { m += this.directionY; if ( m < 0 ) { m = 0; } else if ( m >= this.pages[0].length ) { m = this.pages[0].length - 1; } y = this.pages[0][m].y; } return { x: x, y: y, pageX: i, pageY: m }; }, goToPage: function (x, y, time, easing) { easing = easing || this.options.bounceEasing; if ( x >= this.pages.length ) { x = this.pages.length - 1; } else if ( x < 0 ) { x = 0; } if ( y >= this.pages[x].length ) { y = this.pages[x].length - 1; } else if ( y < 0 ) { y = 0; } var posX = this.pages[x][y].x, posY = this.pages[x][y].y; time = time === undefined ? this.options.snapSpeed || Math.max( Math.max( Math.min(Math.abs(posX - this.x), 1000), Math.min(Math.abs(posY - this.y), 1000) ), 300) : time; this.currentPage = { x: posX, y: posY, pageX: x, pageY: y }; this.scrollTo(posX, posY, time, easing); }, next: function (time, easing) { var x = this.currentPage.pageX, y = this.currentPage.pageY; x++; if ( x >= this.pages.length && this.hasVerticalScroll ) { x = 0; y++; } this.goToPage(x, y, time, easing); }, prev: function (time, easing) { var x = this.currentPage.pageX, y = this.currentPage.pageY; x--; if ( x < 0 && this.hasVerticalScroll ) { x = 0; y--; } this.goToPage(x, y, time, easing); },