做有态度的前端团队

网易FEG前端团队

CSS动态滤镜 filter 在ie下遇到的bug

CSS动态滤镜 filter 在ie下遇到的bug

前言

最初接触滤镜,是为了某些属性去兼容低版本ie而使用的。比如:

  • opacity透明属性,我们会加入filter:alpha(opacity=50);这样的兼容代码

  • background-rgba半透明属性,我们会加入filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr='#4d000000',endcolorstr='#4d000000');

  • 另外还有颜色渐变、透明度渐变等等

看起来还是为我们解决不少问题的。
写这篇文章时特意再去查了一下,发现滤镜还有分类,顺便了了解下:

  • CSS静态滤镜样式

CSS静态滤镜样式的使用方法:{ filter : filtername( parameters1, parameters2, ...) }

  • CSS动态滤镜

动态滤镜可以为页面添加动人的淡入淡出、图象转化效果,它可以分为两种blend(混合)和reveal(显示),前者可以使对象渐渐消失或出现, 后者 提供了24种图象转化的效果。对于动态滤镜的调用除去象在静态滤镜中要定义的滤镜类型,参数等等,还用到脚本语言控制它的状态。

这里只是说了个大概,不详细深入了解。

半透明背景下,事件绑定的bug

最近一个项目,里面有个效果是二级菜单下拉效果,gif体验下:

正常效果-非ie7下

正常效果-非ie7下

BUG效果-ie7下

BUG效果-ie7下

一开始看到这个bug时,觉得肯定是js的冒泡问题啦,我们来看看主要js逻辑代码:

var $subnavwrap = $('.subnav-wrap');//二级菜单的主区域,也是图上带半透明背景的满屏的区域
$subnavwrap.bind('mouseenter',function(){
    //显示下拉二级菜单
}).bind('mouseleave',function(){
    //隐藏二级菜单
})

逻辑就是很简单,鼠标移进二级菜单的区域就显示二级菜单,移出就隐藏菜单,但是在ie7下发现鼠标移到两边半透明区域的时,二级菜单就触发隐藏了!按照开始的思路,开始怀疑自己之前的认知!!!认为mouseenter和mouseleave是会触发事件冒泡的,所以想通过阻止事件冒泡解决,可是未果。
然后看到顶部导航也是类似效果,看他的源码是用mouseout和mouseover,结合setTimeout来达到效果的。决定参考顶条的效果实现,可是调试了很久,大概三个小时,还是解决不了!!!

最后只能通过最原始的debug方法,在代码各个关键语句打印log,一步步debug,后来居然IE7下鼠标在半透明背景的区域是无法触发mouseentermouseleave事件的

下面我们来看个demo(两个div,一个有filter的兼容不透明样式——oDivA,一个是没有——oDivB)
点击查看demo》》》

核心代码如下:
CSS代码

.oDivA{
    width: 400px;
    height: 400px;
    background:rgba(0, 0, 0, 0.4);
    filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr='#4d000000',endcolorstr='#4d000000');
}
.oDivB{
    width: 400px;
    height: 400px;
    background:#000;
    background:rgba(0, 0, 0, 0.4);
}

HTML代码

<div class="oDivA" id="JdivA">
        
</div>
<div class="oDivB" id="JdivB">
        
</div>

JS代码

var odivA = document.getElementById('JdivA'),
    odivB = document.getElementById('JdivB');
odivA.onmouseenter = function() {
    alert('触发mouseenter事件!')
}
odivA.onmouseleave = function() {
    alert('触发mouseleave事件!')
}
odivB.onmouseenter = function() {
    alert('触发mouseenter事件!')
}
odivB.onmouseleave = function() {
    alert('触发mouseleave事件!')
}

测试结果

通过上面的测试demo,使用了兼容ie的半透明属性filter的oDivA,在ie7、8下都是无法触发mouseenter和mouseleave事件的。最后我也测试了其它事件绑定,比如click事件(demo没有,有兴趣的可以自行测试下),也是不支持的。所以这个半透明属性会引起在ie7/8下事件绑定失败,应该是这个属性已经导致整个DOM透掉了,无法扑捉找绑定的事件。所以如果有做一些js相关的操作,建议采用oDivB的兼容写法,在低级浏览器直接降级处理。这里没有测试ie6(已经被抛弃),有需要可以自行测试下。

现在想起,之前也使用过兼容ie的background-size的filter,也会引起js的一些诡异的bug(具体什么bug,太久忘记了)。所以在使用这些滤镜时涉及到js操作的,可以多留个心眼。否则到测试时,一直以为是js的bug,一直苦逼的调试debug。。。谁知道事实上却是一句css引起的惨剧!!!

手机阅读请扫描下方二维码: