/**
* 定义动画
*/
@keyframes fadeIn{
from{opacity: 0;}
to{opacity: 1;}
}
@keyframes fadeOut{
from{opacity: 1;}
to{opacity: 0;}
}
@keyframes hideToLeft{
from{transform: translate3d(0, 0, 0); opacity: 1;}
to{transform: translate3d(-50%, 0, 0); opacity: 1;}
}
@keyframes showFromRight{
from{transform: translate3d(100%, 0, 0); opacity: 1;}
to{transform: translate3d(0, 0, 0); opacity: 1;}
}
@keyframes hideToRight{
from{transform: translate3d(0, 0, 0); opacity: 1;}
to{transform: translate3d(100%, 0, 0); opacity: 1;}
}
@keyframes showFromLeft{
from{transform: translate3d(-50%, 0, 0); opacity: 1;}
to{transform: translate3d(0, 0, 0); opacity: 1;}
}
/**
* 视图容器水平居中
*/
*[data-view-container]{
position: relative;
visibility: hidden;
margin: 0 auto;
overflow: hidden;
transition: height ease 0.5s;
}
*[data-view-container][data-view-state=ready]{
visibility: visible;
}
/**
* 所有视图重叠在一起,默认都不显示
*/
*[data-view=true] {
display: block;
opacity: 0;
z-index: 0;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: auto;
-webkit-overflow-scrolling: touch;
background: #F3F3F3;
box-shadow: 0 0 70px rgba(0, 0, 0, 0.3);
}
/**
* 视图隐藏时要呈现的半透明黑色蒙层。默认不显示
*/
*[data-view=true]:before{
opacity: 0;
content: "";
display: none;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
}
/**
* 活动视图可见
*/
*[data-view=true].active {
opacity: 1;
z-index: 1;
}
/**
* 有条件地引用动画
*/
.view.fadeIn{
animation: fadeIn 0.5s ease-out;
}
.view.fadeOut{
animation: fadeOut 0.5s ease-out;
}
/* 视图含有hideToLeft样式类时播放hideToLeft动画 */
.view.hideToLeft{
animation: hideToLeft 0.5s ease-out;
}
/* 视图向左隐藏时逐渐显示半透明黑色蒙层 */
.view.hideToLeft:before{
display: block;
animation: fadeIn 0.5s linear;
}
/* 视图含有showFromLeft样式类时播放showFromLeft动画 */
.view.showFromLeft{
animation: showFromLeft 0.5s ease-out;
}
/* 视图取消隐藏时逐渐关闭半透明黑色蒙层 */
.view.showFromLeft:before{
display: block;
animation: fadeOut 0.5s linear;
}
/**
* 视图含有hideToRight样式类时播放hideToRight动画。
* z-index要比活动视图的1更高,从而使其不会被活动视图覆盖
*/
.view.hideToRight{
z-index: 2;
animation: hideToRight 0.5s ease-out;
}
/* 视图含有showFromRightn样式类时播放showFromRightn动画 */
.view.showFromRight{
animation: showFromRight 0.5s ease-out;
}
;(function () {
var timer;
/**
* 动画持续时长,需要与css中定义的动画时长一致
* @type {number}
*/
var animationDuration = 500;
/**
* 判断给定的对象是否包含指定名称的样式类
*/
var hasClass = function (obj, clazz) {
if (null == clazz || (clazz = String(clazz).trim()) === "")
return false;
if (obj.classList && obj.classList.contains)
return obj.classList.contains(clazz);
return new RegExp("\\b" + clazz + "\\b", "gim").test(obj.className);
};
/**
* 为指定的对象添加样式类
*/
var addClass = function (obj, clazz) {
if (null == clazz || (clazz = String(clazz).trim()) === "" || hasClass(obj, clazz))
return;
if (obj.classList && obj.classList.add) {
obj.classList.add(clazz);
return;
}
obj.className = (obj.className.trim() + " " + clazz).trim();
};
/**
* 为指定的对象删除样式类
*/
var removeClass = function (obj, clazz) {
if (null == clazz || (clazz = String(clazz).trim()) === "" || !hasClass(obj, clazz))
return;
if (obj.classList && obj.classList.remove) {
obj.classList.remove(clazz);
return;
}
clazz = String(clazz).toLowerCase();
var arr = obj.className.split(/\s+/),
str = "";
for (var i = 0; i < arr.length; i++) {
var tmp = arr[i];
if (null == tmp || (tmp = tmp.trim()) === "")
continue;
if (tmp.toLowerCase() === clazz)
continue;
str += " " + tmp;
}
if (str.length > 0)
str = str.substring(1);
obj.className = str.trim();
};
/**
* 清除给定DOM元素上声明的动画样式
* @param {HTMLElement} obj
*/
var clear = function (obj) {
if (!obj)
return;
"hideToLeft, showFromRight, hideToRight, showFromLeft".split(/\s*,\s*/).forEach(function (className) {
removeClass(obj, className);
});
};
/**
* @param {Object} meta 切换信息
* @param {HTMLElement} meta.srcElement 视图切换时,要离开的当前视图对应的DOM元素。可能为null
* @param {HTMLElement} meta.targetElement 视图切换时,要进入的目标视图对应的DOM元素
* @param {String} type 视图切换方式
* @param {String} trigger 视图切换触发器
* @param {Function} render 渲染句柄
*/
View.setSwitchAnimation(function (meta) {
var srcElement = meta.srcElement,
tarElement = meta.targetElement,
type = meta.type,
trigger = meta.trigger,
render = meta.render;
/**
* 动画播放前清除可能存在的动画样式
*/
clear(srcElement);
clear(tarElement);
/**
* 调用View.js传递而来的渲染句柄,完成活动视图的切换,包括:
* 1. 视图参数的传递
* 2. 活动视图样式类的切换
* 3. leave,ready、enter等事件的触发
*/
render();
var isNav = type === View.SWITCHTYPE_VIEWNAV,
isChange = type === View.SWITCHTYPE_VIEWCHANGE,
isHistoryBack = type === View.SWITCHTYPE_HISTORYBACK,
isHistoryForward = type === View.SWITCHTYPE_HISTORYFORWARD;
if (/\bsafari\b/i.test(navigator.userAgent) && (isHistoryBack || isHistoryForward) && trigger ===
View.SWITCHTRIGGER_NAVIGATOR)
return;
/**
* 视图切换动作是“替换堆栈”的方式,或浏览器不支持对history的操作
*/
if (!View.checkIfBrowserHistorySupportsPushPopAction() || isChange) {
addClass(srcElement, "fadeOut");
addClass(tarElement, "fadeIn");
} else if (isHistoryForward || isNav) {
/**
* 视图切换动作是“压入堆栈”的方式(浏览器前进,或代码触发)
*/
addClass(srcElement, "hideToLeft");
addClass(tarElement, "showFromRight");
} else {
/**
* 视图切换动作是“弹出堆栈”的方式(浏览器后退)
*/
addClass(srcElement, "hideToRight");
addClass(tarElement, "showFromLeft");
}
/**
* 动画播放完成后清除动画样式
*/
clearTimeout(timer);
timer = setTimeout(function () {
clear(srcElement);
clear(tarElement);
}, animationDuration);
});
})();
