如何判断一个DOM元素正在动画,一个CSS“阻塞”JS的例子

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

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

1 if (this.needAnimat && typeof this.animateHideAction == 'function' && this.status != 'hide') {
2   this.animateHideAction.call(this, this.$el);
3 } else
4   this.$el.hide();
在所有组件中,如果设置了animatHideAction回调的,便会执行其中的动画逻辑,针对弹出层来说:

① alert

② loading

③ toast

④ 底部弹出层

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

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

② 动画渐隐渐显

③ 组件底部弹出

......

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

 1 cm-fade-in, .cm-fade-out, .cm-down-in, .cm-down-out, .cm-up-in, .cm-up-out {
 2   -webkit-animation-duration: 0.3s;
 3           animation-duration: 0.3s;
 4   -webkit-animation-fill-mode: both;
 5           animation-fill-mode: both;
 6 }
 7 ......
 8 @keyframes fadeOut {
 9   0% {
10     opacity: 1;
11     -webkit-transform: scale(1);
12             transform: scale(1);
13   }
14   100% {
15     opacity: 0;
16     -webkit-transform: scale(1.185);
17             transform: scale(1.185);
18   }
19 }
20 ......
这个时候我们要实现一个居中弹出层渐隐的效果事实上只需要这样做:

1 el.addClass('cm-fade-out');
3 el.one($.fx.animationEnd, function () {
4   el.removeClass('cm-fade-out');
5   el.hide();
6 });
在动画结束后将对应的动画class移除,再执行真实的hide方法,隐藏dom结构。

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

1 el.addClass('cm-fade-out');
3 setTimeout(function () {
4   el.removeClass('cm-fade-out');
5   el.hide();
6 }, 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严谨,但是一定会保证这逻辑代码执行,从某种程度来说,似乎更好,这里的优化代码是:

 1 var isTrigger = false;
 2 
 3 el.addClass(scope.animateOutClass);
 4 
 5 el.one($.fx.animationEnd, function () {
 6   isTrigger = true;
 7   el.removeClass(scope.animateOutClass);
 8   el.hide();
 9 });
10 
11 setTimeout(function () {
12   if (isTrigger) return;
13 
14   el.removeClass(scope.animateOutClass);
15   el.off($.fx.animationEnd);
16   el.hide();
17 }, 350);
如果animationEnd执行了便不理睬setTimeout,否则便走setTimeout逻辑,也不至于影响业务逻辑,但是这个似乎不是最优解决方案。

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

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

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

 1 function getAllSelectors() {
 2   var ret = [];
 3   for (var i = 0; i < document.styleSheets.length; i++) {
 4     var rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
 5     for (var x in rules) {
 6       if (typeof rules[x].selectorText == 'string') ret.push(rules[x].selectorText);
 7     }
 8   }
 9   return ret;
10 }
11 
12 function selectorExists(selector) {
13   var selectors = getAllSelectors();
14   for (var i = 0; i < selectors.length; i++) {
15     if (selectors[i] == selector) return true;
16   }
17   return false;
18 }
19 
20 //调用方式
21 selectorExists('.class');
22 selectorExists('#id');
上面的代码,本身比较完善了,但是如果某一个css文件跨域的话就完蛋,所以这个方案不靠谱:

① class检测方案本身不靠谱

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

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

① animation-name

② transition的检测

 View Code
核心代码:

 1 var hasAnimationProperty = function (className) {
 2   var animateProprtys = [
 3   //有什么判断的便新增,暂时只判断animation,不同的动画特性,判断方式不一致
 4   //        $.fx.cssPrefix + 'transition',
 5     $.fx.cssPrefix + 'animation-name'
 6   ];
 7   var el = $('<div></div>');
 8   $('body').append(el);
 9 
10   var i, len;
11 
12   //赋予其class
13   el.attr('class', className);
14 
15   for (i = 0, len = animateProprtys.length; i < len; i++) {
16     if (el.css(animateProprtys[i]) != 'none') return true;
17   }
18   s = '';
19   return false;
20 };
21 
22 //false
23 console.log(hasAnimationProperty('test'));
24 //true
25 console.log(hasAnimationProperty('cm-up-out'));
26 //true
27 console.log(hasAnimationProperty('cm-up-in'));
如此一来,便能判断该class是否具有样式属性了,但是这个代码还需要扩展,而且这么也有性能损害,其中涉及到dom操作了,但是想想动画造成到gpu负担,好像也没什么问题



本文转自叶小钗博客园博客,原文链接http://www.cnblogs.com/yexiaochai/p/4135848.html,如需转载请自行联系原作者

相关文章
|
1月前
|
前端开发 JavaScript
CSS 过渡和动画
CSS过渡和动画是用于为网页元素添加动态效果的两种重要技术
127 73
|
1月前
|
前端开发 JavaScript
如何使用CSS过渡实现页面元素的淡入淡出效果?
如何使用CSS过渡实现页面元素的淡入淡出效果?
122 79
|
5天前
|
JavaScript 前端开发 API
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
1月前
|
前端开发
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
48 1
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
|
2月前
|
人工智能 程序员 UED
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
151 21
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
2月前
|
前端开发 JavaScript
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
66 14
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
2月前
css3 svg制作404页面动画效果HTML源码
css3 svg制作404页面动画效果HTML源码
70 34
|
2月前
html+js+css实现的建筑方块立体数字时钟源码
html+js+css实现的建筑方块立体数字时钟源码
102 33
|
2月前
jQuery+CSS3实现404背景游戏动画源码
jQuery+CSS3实现404背景游戏动画源码
62 22
|
3月前
一个好看的小时钟html+js+css源码
一个好看的小时钟html+js+css源码
125 24

热门文章

最新文章