一般情况下CSS不会直接影响JS的程序逻辑,但是以CSS实现动画的话,这个便不太确定了,这个故事发生在与UED迁移全局样式的过程。

曾经我有一段实现弹出层隐藏动画的代码是这个样子的:

 if (this.needAnimat && typeof this.animateHideAction == 'function' && this.status != 'hide') {
this.animateHideAction.call(this, this.$el);
} else
this.$el.hide();

在所有组件中,如果设置了animatHideAction回调的,便会执行其中的动画逻辑,针对弹出层来说:

① alert

② loading

③ toast

④ 底部弹出层

等组件中动画效果各不相同:

① 动画显示时下沉,隐藏时上浮

② 动画渐隐渐显

③ 组件底部弹出

......

针对通用的动画,一般框架会提供一段CSS类做处理,不满足的情况,各个业务团队便需要自己封装:

 cm-fade-in, .cm-fade-out, .cm-down-in, .cm-down-out, .cm-up-in, .cm-up-out {
-webkit-animation-duration: 0.3s;
animation-duration: 0.3s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
......
@keyframes fadeOut {
0% {
opacity:;
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
opacity:;
-webkit-transform: scale(1.185);
transform: scale(1.185);
}
}
......

这个时候我们要实现一个居中弹出层渐隐的效果事实上只需要这样做:

 el.addClass('cm-fade-out');

 el.one($.fx.animationEnd, function () {
el.removeClass('cm-fade-out');
el.hide();
});

在动画结束后将对应的动画class移除,再执行真实的hide方法,隐藏dom结构。

其实,我记得是去年的时候我是这么处理这个代码的,当时被一个同事骂了不严谨,今年就使用了animationEnd接口:

 el.addClass('cm-fade-out');

 setTimeout(function () {
el.removeClass('cm-fade-out');
el.hide();
}, 340);

这里问题来了,使用animationEnd与setTimeout去除动画class,或者执行业务真实逻辑,到底哪家强,哪个合适?

第一反应都是认为animationEnd比较合理,于是我最近遇到了一个问题:

请求一个数据,loading一直在那里转,永远不消失了!而且执行了hideLoading的操作,与数据延迟毫无关系

于是我开始愉快的定位,当时搞了一会,发现loading的动画没有执行,仔细一定位,发现css中的动画相关的css丢了,于是造成的结果是:

el.addClass('cm-fade-out');

这个代码变成了单纯的class增加,并没有执行动画,也就是,animationEnd的事件没有触发,于是没有执行hide方法,所以loading框就一直在那里转

问题定位到了,解决方案就非常简单了,将css的动画加上即可;但是也说明了,这段代码中JS代码逻辑依赖了CSS相关,从而导致了CSS阻塞JS的假象

这里如果使用setTimeout的话虽然感觉没有animationEnd严谨,但是一定会保证这逻辑代码执行,从某种程度来说,似乎更好,这里的优化代码是:

 var isTrigger = false;

 el.addClass(scope.animateOutClass);

 el.one($.fx.animationEnd, function () {
isTrigger = true;
el.removeClass(scope.animateOutClass);
el.hide();
}); setTimeout(function () {
if (isTrigger) return; el.removeClass(scope.animateOutClass);
el.off($.fx.animationEnd);
el.hide();
}, 350);

如果animationEnd执行了便不理睬setTimeout,否则便走setTimeout逻辑,也不至于影响业务逻辑,但是这个似乎不是最优解决方案。

因为我没有办法,因为这里得有350ms的延迟,在不存在css动画的时候,似乎整个弹出层消失逻辑都变得2B了起来,比较好的方式是,我在执行动画前检测是否具有该css比较靠谱

所以,javascript检测CSS的某一个className是否存在,似乎变成了关键,但是就算就算能找到具有某class,这个class也未必具有动画属性,或者该属性被篡改

况且使用document.styleSheets方式去判断某个样式class是否存在,经过之前的经验,本身就是大坑,还会有跨域什么的场景,坑死人,比如这个代码:

 function getAllSelectors() {
var ret = [];
for (var i = 0; i < document.styleSheets.length; i++) {
var rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
for (var x in rules) {
if (typeof rules[x].selectorText == 'string') ret.push(rules[x].selectorText);
}
}
return ret;
} function selectorExists(selector) {
var selectors = getAllSelectors();
for (var i = 0; i < selectors.length; i++) {
if (selectors[i] == selector) return true;
}
return false;
} //调用方式
selectorExists('.class');
selectorExists('#id');

上面的代码,本身比较完善了,但是如果某一个css文件跨域的话就完蛋,所以这个方案不靠谱:

① class检测方案本身不靠谱

② 就算class靠谱,也不能保证class就具有动画相关属性,所以也不靠谱!

最终我想到的方案还是对动画属性做检测,检测点主要在动画属性的检测,比如关键属性:

① animation-name

② transition的检测

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
<style> .cm-fade-in {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
} .cm-fade-out {
-webkit-animation-name: fadeOut;
animation-name: fadeOut;
} @-webkit-keyframes fadeIn {
0% {
opacity: 0;
-webkit-transform: scale(0.815);
transform: scale(0.815);
}
100% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
} @keyframes fadeIn {
0% {
opacity: 0;
-webkit-transform: scale(0.815);
transform: scale(0.815);
}
100% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
}
@-webkit-keyframes fadeOut {
0% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
opacity: 0;
-webkit-transform: scale(1.185);
transform: scale(1.185);
}
}
@keyframes fadeOut {
0% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
opacity: 0;
-webkit-transform: scale(1.185);
transform: scale(1.185);
}
}
.cm-down-in {
-webkit-animation-name: downIn;
animation-name: downIn;
} .cm-down-out {
-webkit-animation-name: downOut;
animation-name: downOut;
} @-webkit-keyframes downIn {
0% {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
100% {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
} @keyframes downIn {
0% {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
100% {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@-webkit-keyframes downOut {
0% {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
@keyframes downOut {
0% {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
.cm-up-in {
-webkit-animation-name: upIn;
animation-name: upIn;
} .cm-up-out {
-webkit-animation-name: upOut;
animation-name: upOut;
}
</style>
</head>
<body>
<script type="text/javascript">
var hasAnimationProperty = function (className) {
var animateProprtys = [
//有什么判断的便新增,暂时只判断animation,不同的动画特性,判断方式不一致
// $.fx.cssPrefix + 'transition',
$.fx.cssPrefix + 'animation-name'
];
var el = $('<div></div>');
$('body').append(el); var i, len; //赋予其class
el.attr('class', className); for (i = 0, len = animateProprtys.length; i < len; i++) {
if (el.css(animateProprtys[i]) != 'none') return true;
}
s = '';
return false;
}; //false
console.log(hasAnimationProperty('test'));
//true
console.log(hasAnimationProperty('cm-up-out'));
//true
console.log(hasAnimationProperty('cm-up-in')); </script>
</body>
</html>

核心代码:

 var hasAnimationProperty = function (className) {
var animateProprtys = [
//有什么判断的便新增,暂时只判断animation,不同的动画特性,判断方式不一致
// $.fx.cssPrefix + 'transition',
$.fx.cssPrefix + 'animation-name'
];
var el = $('<div></div>');
$('body').append(el); var i, len; //赋予其class
el.attr('class', className); for (i = 0, len = animateProprtys.length; i < len; i++) {
if (el.css(animateProprtys[i]) != 'none') return true;
}
s = '';
return false;
}; //false
console.log(hasAnimationProperty('test'));
//true
console.log(hasAnimationProperty('cm-up-out'));
//true
console.log(hasAnimationProperty('cm-up-in'));

如此一来,便能判断该class是否具有样式属性了,但是这个代码还需要扩展,而且这么也有性能损害,其中涉及到dom操作了,但是想想动画造成到gpu负担,好像也没什么问题

最新文章

  1. project server 2016 新功能
  2. maven添加自己的jar包到本地仓库
  3. C#内存释放
  4. typedef和#define的用法与区别
  5. C++动态数组
  6. USB模式安装CentOS6.4_minimal
  7. 生成唯一的id(转)
  8. javascript之Function函数
  9. Tuxedo学习门户网站
  10. (ArcGIS API For Silverlight )QueryTask 跨层查询,和监控完整的查询!
  11. 201521123022 《Java程序设计》 第六周学习总结
  12. Spring-boot:5分钟整合Dubbo构建分布式服务
  13. 【二分图】P3386洛谷模板
  14. mongodb+express+nodejs(登陆退出)
  15. WebSocket+Java 私聊、群聊实例
  16. TRAC-IK机器人运动学求解器
  17. Coroutines declared with async/await syntax is the preferred way of writing asyncio applications. For example, the following snippet of code (requires Python 3.7+) prints “hello”, waits 1 second, and
  18. uboot i2c 操作函数记录
  19. 详解C#泛型(一)
  20. iOS: 获取UITableViewCell上添加的子控件对应的cell

热门文章

  1. 前端开发小白必学技能—非关系数据库又像关系数据库的MongoDB快速入门命令(2)
  2. HTML5- Canvas入门(五)
  3. 用lucene替代mysql读库的尝试
  4. 抛弃jQuery:DOM API之操作元素
  5. .NET开发邮件发送功能的全面教程(含邮件组件源码)
  6. [数据库基础]——图解JOIN
  7. The type javax.ws.rs.core.MediaType cannot be resolved. It is indirectly referenced from required .class files
  8. Javascript 相关文章 —— 性能
  9. .Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json、反序列化json示例教程
  10. HTML5结构元素