Last active
May 23, 2018 05:35
-
-
Save thinkgarden/e0184ccf0481f2a64b2e016c56a1fa36 to your computer and use it in GitHub Desktop.
[parallax] A simple parallax animation plugin for jQuery #mobile #parallax #js
This file contains hidden or 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
!function($) { | |
var startPos, // 开始触摸点(X/Y坐标) | |
endPos, | |
stage, // 用于标识 onStart/onMove/onEnd 流程的第几阶段,解决 onEnd 重复调用 | |
offset, // 偏移距离 | |
direction, // 翻页方向 | |
curPage, // page 当前页 | |
pageCount, // page 数量 | |
pageWidth, // page 宽度 | |
pageHeight, // page 高度 | |
$pages, // page 外部 wrapper | |
$pageArr, // page 列表 | |
$animateDom, // 所有设置 [data-animate] 的动画元素 | |
options, // 最终配置项 | |
touchDown = false, // 手指已按下 (取消触摸移动时 transition 过渡) | |
movePrevent = true; // 阻止滑动 (动画过程中手指按下不可阻止) | |
$.fn.parallax = function(opts) { | |
options = $.extend({}, $.fn.parallax.defaults, opts); | |
return this.each(() => { | |
$pages = $(this); | |
$pageArr = $pages.find('.page'); | |
init(); | |
}) | |
} | |
$.fn.parallax.defaults = { | |
direction: 'vertical', | |
swipeAnim: 'default', | |
loading: false, | |
onchange: function() { }, | |
} | |
function init() { | |
if (options.loading) { | |
} else { | |
movePrevent = false; | |
} | |
//页面数量,当前页,页面高度,宽度,设置Container样式 | |
curPage = 0; | |
direction = 'stay'; | |
pageCount = $pageArr.length; // 获取 page 数量 | |
pageWidth = document.documentElement.clientWidth; // 获取手机屏幕宽度 | |
pageHeight = document.documentElement.clientHeight; // 获取手机屏幕高度 | |
$animateDom = $('[data-animation]'); | |
for (var i = 0; i < pageCount; i++) { // 批量添加 data-id | |
$($pageArr[i]).attr('data-id', i + 1); | |
} | |
$pages.addClass(options.direction) // 添加 direction 类 | |
.addClass(options.swipeAnim); // 添加 swipeAnim 类 | |
$pageArr.css({ // 初始化 page 宽高 | |
'width': pageWidth + 'px', | |
'height': pageHeight + 'px' | |
}); | |
if (!options.loading) { | |
$($pageArr[curPage]).addClass('current'); | |
options.onchange(curPage, $pageArr[curPage], direction); | |
// animShow(); | |
} | |
} | |
// 当前页动画显示 | |
function animShow() { | |
$animateDom.css({ | |
'-webkit-animation': 'none', | |
'display': 'none' // 解决部分 Android 机型 DOM 不自动重绘的 bug | |
}); | |
} | |
function animatePage(newPage) { | |
curPage = newPage; | |
if (options.swipeAnim === 'default') { | |
var newOffset = 0; | |
options.direction === 'horizontal' ? | |
newOffset = newPage * (-pageWidth) : | |
newOffset = newPage * (-pageHeight); | |
options.direction === 'horizontal' ? | |
$pages.css({ '-webkit-transform': 'matrix(1, 0, 0, 1, ' + newOffset + ', 0)' }) : | |
$pages.css({ '-webkit-transform': 'matrix(1, 0, 0, 1, 0, ' + newOffset + ')' }); | |
} | |
} | |
function dragToMove() { | |
console.log('dragToMove') | |
} | |
function addDirecClass() { | |
if (options.direction === 'horizontal') { | |
if (endPos >= startPos) { | |
$pages.removeClass('forward').addClass('backward'); | |
} else if (endPos < startPos) { | |
$pages.removeClass('backward').addClass('forward'); | |
} | |
} else { | |
if (endPos >= startPos) { | |
$pages.removeClass('forward').addClass('backward'); | |
} else if (endPos < startPos) { | |
$pages.removeClass('backward').addClass('forward'); | |
} | |
} | |
} | |
function isHeadOrTail() { | |
if ((endPos > startPos) && curPage === 0 || | |
(endPos <= startPos && curPage === pageCount - 1)) { | |
return true; | |
} | |
return false; | |
} | |
const onStart = (e) => { | |
if (movePrevent === true) { | |
event.preventDefault(); | |
return false; | |
} | |
touchDown = true; | |
options.direction === 'horizontal' ? startPos = e.pageX : startPos = e.pageY; | |
if (options.swipeAnim === 'default') { | |
$pages.addClass('drag'); // 阻止过渡效果 | |
// offset 怎么获得 | |
offset = $pages.css("-webkit-transform") | |
.replace("matrix(", "") | |
.replace(")", "") | |
.split(","); | |
options.direction === 'horizontal' ? | |
offset = parseInt(offset[4]) : | |
offset = parseInt(offset[5]); | |
} | |
stage = 1; | |
} | |
const onMove = (e) => { | |
if (movePrevent === true || touchDown === false) { | |
event.preventDefault(); | |
return false; | |
} | |
event.preventDefault(); | |
options.direction === 'horizontal' ? endPos = e.pageX : endPos = e.pageY; | |
addDirecClass(); // 添加方向类 | |
if (options.drag && !isHeadOrTail()) { // 拖拽时调用 | |
dragToMove(); | |
} | |
stage = 2; | |
} | |
const onEnd = (e) => { | |
if (movePrevent === true || stage !== 2) { | |
// event.preventDefault(); | |
// return false; | |
} else { | |
touchDown = false; | |
options.direction === 'horizontal' ? endPos = e.pageX : endPos = e.pageY; | |
if (options.swipeAnim === 'default' && !isHeadOrTail()) { | |
$pages.removeClass('drag'); | |
if (Math.abs(endPos - startPos) <= 50) { | |
animatePage(curPage); | |
direction = 'stay'; | |
} | |
else if (endPos >= startPos) { | |
animatePage(curPage - 1); | |
direction = 'backward'; | |
} | |
else if (endPos < startPos) { | |
animatePage(curPage + 1); | |
direction = 'forward'; | |
} | |
} | |
stage = 3; | |
} | |
} | |
// 事件代理绑定 | |
$(document).on('touchstart', '.page', (e) => { | |
onStart(e.changedTouches[0]) | |
}).on('touchmove', '.page', (e) => { | |
onMove(e.changedTouches[0]); | |
}).on('touchend', '.page', (e) => { | |
onEnd(e.changedTouches[0]); | |
}).on('webkitAnimationEnd webkitTransitionEnd', '.pages', function() { | |
if (direction !== 'stay') { | |
setTimeout(function() { | |
$(".back").hide().removeClass("back"); | |
$(".front").show().removeClass("front"); | |
$pages.removeClass('forward backward animate'); | |
}, 10); | |
$($pageArr.removeClass('current').get(curPage)).addClass('current'); | |
options.onchange(curPage, $pageArr[curPage], direction); // 执行回调函数 | |
// animShow(); | |
} | |
}); | |
}(Zepto) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment