这次的3d轮播主要是因为之前页面构建的同事想要做没做成的原因 ,所以不如自己做吧。

3d轮播着实很简单,首先需要正常的轮播组件:需要由next,prev,jump等句柄,绑定mouseover,mouseout事件(为了鼠标悬停时暂停自动轮播),有初始化setup。

有了轮播组件之后就是要在轮播过程中加入动画方法,主要思路是这样的:

1、需要在初始化的时候构建动画需要的节点。

构建的时候需要一个全局的节点cube来把所以需要动画的节点都放在里面。

然后再去构建自己动画不同的节点。

最后把需要的样式,即Css3 animation方法塞到页面初始化之前创建的style节点中去,并提供执行这段css的css代码Css3code(每种方法各有不同)

2、在jump里与普通轮播不同,需要先设定css3动画结束后的事件(js提供了这样的事件,没有的话可以用setTimeout,但是如果都不支持这个,动画也就不支持了吧……)。这个事件也就是恢复状态用,把真正动画的节点Cube隐藏掉,真实节点显示出来,处理index等。

然后,把全局节点cube节点显示出来,把真正的节点隐藏掉。

最后,切换需要轮播的图片链接(轮播需要),再把Css3code 这段样式加到cube节点上,这样它就开始自己动画了

总结一下就是这两步是新的:就是在切换的时候显示动画节点,动画完了,隐藏掉。

下面有些共用方法:

1、存放动画方法(也就是keyframes)需要创建一个style节点。它的初始化发生在最最开始初始化的时候。下面这段纯属抄袭:

var cssDom = document.createElement('style');
var cssId = 'mayloveless' + (+new Date());
var cssSheet = null;
var that = {};
cssDom.setAttribute('type','text/css');
cssDom.setAttribute('id', cssId);
document.head.appendChild(cssDom);
for(var i = 0,len = document.styleSheets.length; i < len; i += 1){
        if(document.styleSheets[i].ownerNode.id === cssId){
                cssSheet = document.styleSheets[i];
        break;
        }
}
//这就是把css code塞到节点中的方法。
that.addRule = function(selector, cssText){
    var rules = cssSheet.rules || cssSheet.cssRules;
    if(cssSheet.addRule){
         cssSheet.addRule(selector, cssText, rules.length);
    }else if(cssSheet.insertRule){
         cssSheet.insertRule(selector + ' {' + cssText + '}', rules.length);
    }
};

2、对于变态的前缀也有个兼容。下面这段也是抄袭:

var PREFIX = /^(Moz|(w|W)ebkit|O|ms)(?=[A-Z])/;
var addPrefix = function(text){
            for ( var p in document.createElement('div').style ) {
//也就是各种前缀试一圈,然后看看支持哪个,支持哪个就是哪个
                if( PREFIX.test(p) ) {
                    var pre = p.match(PREFIX)[0];
                    var css3Text = '-'+pre+'-'+text;
                    return [css3Text,pre];
                }
            }
            return [text,''];
        };

3、同理,动画结束事件的兼容是这样的,下面这段是自己写的,毫无技术含量

//把对应的名字列出一个映射map来就好    

var ANIMATION_END_NAMES = {
        "moz" : "animationend"
        ,"webkit" : "webkitAnimationEnd"
        ,"ms" : "MSAnimationEnd"
        ,"o" : "oAnimationEnd"
 }
eventType = ANIMATION_END_NAMES[addPrefix('animation')[1].toLowerCase()];

4、最后就是动画方法了,即那个css的code:一共三个效果,翻牌,立方体翻滚,放大旋转。

var CSSTEXT = {
    'flip': ''+
        '0% { '+addPrefix('transform')[0]+': rotateX(0);} '+
        '100% { '+addPrefix('transform')[0]+': rotateX(-180deg);}'
    ,'cube' :''+
        '0% {'+addPrefix('transform')[0]+': rotate3d(1,0,0,0); }'+
        '100% { '+addPrefix('transform')[0]+': rotate3d(1,0,0,-90deg); }'
    ,'scale':''+
        '0% { opacity:1; }'+
        '60% { '+addPrefix('transform')[0]+': rotateZ(-3deg) scale(0.9); opacity:0.8; }'+            
        '100% { '+addPrefix('transform')[0]+': rotateZ(3deg) scale(1.2); opacity:0; }'            
};

以上动画方法就结束了。还有考虑一个轮播兼容的问题:不支持css3的用普通的轮播。

以下是简略代码:中心思想是判断有没有TransformStyle属性在样式里,然后给它赋值preserve-3d,看它能不能被附上,能的话就可以3d。不能的话用同样的方法试试BackfaceVisibility这个属性,能的话且是放大旋转的效果的话,也可以3d

//_vendor为前缀
var _canRun3d = _vendor+'TransformStyle';
 if(_canRun3d in  testDiv.style){
    testDiv.style[_canRun3d] = 'preserve-3d';
  }
 if( testDiv.style[_canRun3d] || ( _vendor+'BackfaceVisibility' in testDiv.style && animationType ==='scale') ){
//3d轮播    
}else{
//普通轮播
}

首先要解释的是TransformStyle ,它是用来设置3d位置的,

如果值preserve-3d的话,是保留3d位置的,也就是说它是真正的立体位置摆放的。而另一个值:flat则不然。

像这次的轮播就是把动画作用于cube父节点,然后子节点保留相对位置,动画的时候父节点动画,

它和子节点是一个整体。而flat的话就只能子节点继承动画,分别动画了,这就不符合动画的初衷了。

(p.s ie10 支持flat不支持 preserve-3d)

之所以这么恶心的还判断了个效果类型就是因为放大旋转的效果不是真正的3d,

不受这个TransformStyle 的影响。

所以最后没有解决的问题就是:

低版本Chrome(加上360极速 )最少是26以下,它本身是可以有这个transform-style: preserve-3d

的,因为我把值附上之后,是可以访问到的,若不支持是为空的。

但它却不能支持应有的效果!!!!!

真的不知道如何才能判断是否支持的浏览器了……导致我现在效果好搓啊,就一个放大效果……sigh………

++++++++++++++++++

上面的问题 查到为什么了,实在没辙,貌似是Chrome的bug!BackfaceVisibility这个属性支持但不起作用,这个问题已经好久了,直到Chrome26还不行。sigh……难道我要再判断浏览器版本嘛???略复杂啊这……

https://code.google.com/p/chromium/issues/detail?id=39044

参考资料:虽然当初并不是参考得这篇文章,但这篇文章总结的动画部分比较好

http://beiyuu.com/css3-animation/

记于2013年09月16日 EOF