本身動手豐衣足食,爲Zepto添加Slide動畫效果

一.原因css

      公司的移動端項目,採用zepto爲主要框架,可是zepto畢竟是精簡版的jquery,體積小了,功能天然沒有這麼強大,特別是動畫和選擇器這兩塊,須要咱們本身去拓展。html

      在項目開發過程當中,不少頁面過渡須要用到動畫,簡單的show/hide過渡太生硬,對用戶不友好,而且移動端大多都是採用slide效果,此文主要是爲zepto拓展slide動畫。jquery

 

二.發現git

      從zepto的在線文檔上能夠發現一個發佈在github上的動畫模塊,可是缺乏slide效果,度娘上找了找,相關的極少,只發現了一個slideDown的例子,因此咱們就照着這個例子寫了幾個經常使用的slide動畫。github

 

三.行動web

       首先,咱們把動畫方向分爲上下滑動左右滑動,滑動形式分爲元素自身的伸縮相對位移 api

       1.左右slideapp

       這應該是最經常使用的一個效果框架

       貼上代碼:註釋部分二選一, slideLeft 和 slideRight 的滑動形式必須設爲一致,否則沒法工做ide

       $.fn.slideRight = function (speed, callback) {
            //獲取元素position
            var position = this.css('position');
            this.show().css({
                position: 'absolute',
                visibility: 'hidden'
            });
            $('html,body').css({
                overflow: 'hidden',
                height: '100%'
            });
            //獲取元素寬度
            var width = this.width() === 0 ? $(window).width() : this.width();

            //-------經過伸縮元素寬度實現動畫-------
            //return this.css({
            //    top: $(window).scrollTop(),
            //    width: 0,
            //    position: position,
            //    visibility: 'visible',
            //    overflow: 'auto'
            //}).animate({ width: width }, speed, null, callback);

            //-------經過移動元素相對位置實現動畫-------
            return this.css({
                top: $(window).scrollTop(),
                left: -width,
                position: position,
                visibility: 'visible',
                overflow: 'auto',
            }).animate({ left: 0 }, speed, null, callback);
        };

        $.fn.slideLeft = function (speed, callback) {
            //獲取元素position
            var position = this.css('position');
            this.show().css({
                position: 'absolute',
                visibility: 'hidden'
            });
            $('html,body').css({
                overflow: '',
                height: ''
            });
            //獲取元素寬度
            var width = this.width();
            //-------經過伸縮元素寬度實現動畫-------
            //return this.css({
            //    top: 0,
            //    position: position,
            //    visibility: 'visible',
            //    overflow: 'auto'
            //}).animate({ width: 0 }, speed, null, callback);

            //-------經過移動元素相對位置實現動畫-------
            return this.css({
                top: 0,
                position: position,
                visibility: 'visible',
                overflow: 'auto'
            }).animate({ left: -width }, speed, null, callback);
        };
View Code

    左右位移效果圖:                                                                                                         

         

    左右伸縮效果圖:

    

 

   2.上下slide

      貼上代碼:註釋部分二選一, slideUp 和 slideDown 的滑動形式必須設爲一致,否則沒法工做

       $.fn.slideDown = function (speed, callback) {
            //獲取元素position
            var position = this.css('position');
            this.show().css({
                position: 'absolute',
                visibility: 'hidden'
            });
            $('html,body').css({
                overflow: 'hidden',
                height: '100%'
            });
            //獲取元素高度
            var height = this.height() === 0 ? $(window).height() : this.height();

            //-------經過伸縮元素高度實現動畫-------
            //return this.css({
            //    position: position,
            //    visibility: 'visible',
            //    overflow: 'auto',
            //    height: 0
            //}).animate({ height: height, top: $(window).scrollTop() }, speed, null, callback);

            //-------經過移動元素相對位置實現動畫-------
            return this.css({
                top: -height,
                left: 0,
                position: position,
                visibility: 'visible',
                overflow: 'auto'
            }).animate({ top: $(window).scrollTop() }, speed, null, callback);
        };

        $.fn.slideUp = function (speed, callback) {
            //獲取元素position
            var position = this.css('position');
            this.show().css({
                position: 'absolute',
                visibility: 'auto'
            });
            $('html,body').css({
                overflow: '',
                height: ''
            });
            //獲取元素高度
            var height = this.height();
            //-------經過伸縮元素高度實現動畫-------
            //return this.css({
            //    position: position,
            //    visibility: 'visible',
            //    overflow: 'hidden',
            //    height: height
            //}).animate({ height: 0 }, speed, null, callback);

            //-------經過移動元素相對位置實現動畫-------
            return this.css({
                left: 0,
                position: position,
                visibility: 'visible',
                overflow: 'auto'
            }).animate({ top: -height }, speed, null, callback);
        };
View Code

     上下位移效果圖:                                                                                                          

          

    上下伸縮效果圖:

     

 

四.結束

      這樣,咱們在項目中就能愉快的使用動畫了。

      順便附上整個動畫模塊,但在這以前必須先添加上animate模塊,由於zepto自己是不具備animate事件的,許多模塊都是單獨分出去的,能夠參考這裏,代碼咱們能夠從github中的animate模塊複製進去。

    

    //animate模塊
    ; (function ($, undefined) {
        var prefix = '', eventPrefix,
          vendors = { Webkit: 'webkit', Moz: '', O: 'o' },
          testEl = document.createElement('div'),
          supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,
          transform,
          transitionProperty, transitionDuration, transitionTiming, transitionDelay,
          animationName, animationDuration, animationTiming, animationDelay,
          cssReset = {}

        function dasherize(str) { return str.replace(/([A-Z])/g, '-$1').toLowerCase() }
        function normalizeEvent(name) { return eventPrefix ? eventPrefix + name : name.toLowerCase() }

        if (testEl.style.transform === undefined) $.each(vendors, function (vendor, event) {
            if (testEl.style[vendor + 'TransitionProperty'] !== undefined) {
                prefix = '-' + vendor.toLowerCase() + '-'
                eventPrefix = event
                return false
            }
        })

        transform = prefix + 'transform'
        cssReset[transitionProperty = prefix + 'transition-property'] =
        cssReset[transitionDuration = prefix + 'transition-duration'] =
        cssReset[transitionDelay = prefix + 'transition-delay'] =
        cssReset[transitionTiming = prefix + 'transition-timing-function'] =
        cssReset[animationName = prefix + 'animation-name'] =
        cssReset[animationDuration = prefix + 'animation-duration'] =
        cssReset[animationDelay = prefix + 'animation-delay'] =
        cssReset[animationTiming = prefix + 'animation-timing-function'] = ''

        $.fx = {
            off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined),
            speeds: { _default: 400, fast: 200, slow: 600 },
            cssPrefix: prefix,
            transitionEnd: normalizeEvent('TransitionEnd'),
            animationEnd: normalizeEvent('AnimationEnd')
        }

        $.fn.animate = function (properties, duration, ease, callback, delay) {
            if ($.isFunction(duration))
                callback = duration, ease = undefined, duration = undefined
            if ($.isFunction(ease))
                callback = ease, ease = undefined
            if ($.isPlainObject(duration))
                ease = duration.easing, callback = duration.complete, delay = duration.delay, duration = duration.duration
            if (duration) duration = (typeof duration == 'number' ? duration :
                            ($.fx.speeds[duration] || $.fx.speeds._default)) / 1000
            if (delay) delay = parseFloat(delay) / 1000
            return this.anim(properties, duration, ease, callback, delay)
        }

        $.fn.anim = function (properties, duration, ease, callback, delay) {
            var key, cssValues = {}, cssProperties, transforms = '',
                that = this, wrappedCallback, endEvent = $.fx.transitionEnd,
                fired = false

            if (duration === undefined) duration = $.fx.speeds._default / 1000
            if (delay === undefined) delay = 0
            if ($.fx.off) duration = 0

            if (typeof properties == 'string') {
                // keyframe animation
                cssValues[animationName] = properties
                cssValues[animationDuration] = duration + 's'
                cssValues[animationDelay] = delay + 's'
                cssValues[animationTiming] = (ease || 'linear')
                endEvent = $.fx.animationEnd
            } else {
                cssProperties = []
                // CSS transitions
                for (key in properties)
                    if (supportedTransforms.test(key)) transforms += key + '(' + properties[key] + ') '
                    else cssValues[key] = properties[key], cssProperties.push(dasherize(key))

                if (transforms) cssValues[transform] = transforms, cssProperties.push(transform)
                if (duration > 0 && typeof properties === 'object') {
                    cssValues[transitionProperty] = cssProperties.join(', ')
                    cssValues[transitionDuration] = duration + 's'
                    cssValues[transitionDelay] = delay + 's'
                    cssValues[transitionTiming] = (ease || 'linear')
                }
            }

            wrappedCallback = function (event) {
                if (typeof event !== 'undefined') {
                    if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from "below"
                    $(event.target).unbind(endEvent, wrappedCallback)
                } else
                    $(this).unbind(endEvent, wrappedCallback) // triggered by setTimeout

                fired = true
                $(this).css(cssReset)
                callback && callback.call(this)
            }
            if (duration > 0) {
                this.bind(endEvent, wrappedCallback)
                // transitionEnd is not always firing on older Android phones
                // so make sure it gets fired
                setTimeout(function () {
                    if (fired) return
                    wrappedCallback.call(that)
                }, ((duration + delay) * 1000) + 25)
            }

            // trigger page reflow so new elements can animate
            this.size() && this.get(0).clientLeft

            this.css(cssValues)

            if (duration <= 0) setTimeout(function () {
                that.each(function () { wrappedCallback.call(this) })
            }, 0)

            return this
        }

        testEl = null
    })(Zepto)
    //動畫效果模塊
    ; (function ($, undefined) {
        var document = window.document, docElem = document.documentElement,
          origShow = $.fn.show, origHide = $.fn.hide, origToggle = $.fn.toggle

        function anim(el, speed, opacity, scale, callback) {
            if (typeof speed == 'function' && !callback) callback = speed, speed = undefined
            var props = { opacity: opacity }
            if (scale) {
                props.scale = scale
                el.css($.fx.cssPrefix + 'transform-origin', '0 0')
            }
            return el.animate(props, speed, null, callback);
        }

        function hide(el, speed, scale, callback) {
            return anim(el, speed, 0, scale, function () {
                origHide.call($(this))
                callback && callback.call(this)
            })
        }

        $.fn.show = function (speed, callback) {
            origShow.call(this)
            //不是很理解做者的想法,若是這裏繼續執行下去,全部調用zepto原生show事件的元素,都會被這個事件覆蓋,而且透明度都爲被設爲1...
            if (speed === undefined) return origShow.call(this) // 原版爲:if (speed === undefined) speed = 0
            else this.css('opacity', 0)
            return anim(this, speed, 1, '1,1', callback)
        }

        $.fn.hide = function (speed, callback) {
            if (speed === undefined) return origHide.call(this)
            else return hide(this, speed, '0,0', callback)
        }

        $.fn.toggle = function (speed, callback) {
            if (speed === undefined || typeof speed == 'boolean')
                return origToggle.call(this, speed)
            else return this.each(function () {
                var el = $(this)
                el[el.css('display') == 'none' ? 'show' : 'hide'](speed, callback)
            })
        }

        $.fn.fadeTo = function (speed, opacity, callback) {
            return anim(this, speed, opacity, null, callback)
        }

        $.fn.fadeIn = function (speed, callback) {
            var target = this.css('opacity')
            if (target > 0) this.css('opacity', 0)
            else target = 1
            return origShow.call(this).fadeTo(speed, target, callback)
        }

        $.fn.fadeOut = function (speed, callback) {
            return hide(this, speed, null, callback)
        }

        $.fn.fadeToggle = function (speed, callback) {
            return this.each(function () {
                var el = $(this)
                el[
                  (el.css('opacity') == 0 || el.css('display') == 'none') ? 'fadeIn' : 'fadeOut'
                ](speed, callback)
            })
        }

        $.fn.slideDown = function (speed, callback) {
            //獲取元素position
            var position = this.css('position');
            this.show().css({
                position: 'absolute',
                visibility: 'hidden'
            });
            $('html,body').css({
                overflow: 'hidden',
                height: '100%'
            });
            //獲取元素高度
            var height = this.height() === 0 ? $(window).height() : this.height();

            //-------經過伸縮元素高度實現動畫-------
            //return this.css({
            //    position: position,
            //    visibility: 'visible',
            //    overflow: 'auto',
            //    height: 0
            //}).animate({ height: height, top: $(window).scrollTop() }, speed, null, callback);

            //-------經過移動元素相對位置實現動畫-------
            return this.css({
                top: -height,
                left: 0,
                position: position,
                visibility: 'visible',
                overflow: 'auto'
            }).animate({ top: $(window).scrollTop() }, speed, null, callback);
        };

        $.fn.slideUp = function (speed, callback) {
            //獲取元素position
            var position = this.css('position');
            this.show().css({
                position: 'absolute',
                visibility: 'auto'
            });
            $('html,body').css({
                overflow: '',
                height: ''
            });
            //獲取元素高度
            var height = this.height();
            //-------經過伸縮元素高度實現動畫-------
            //return this.css({
            //    position: position,
            //    visibility: 'visible',
            //    overflow: 'hidden',
            //    height: height
            //}).animate({ height: 0 }, speed, null, callback);

            //-------經過移動元素相對位置實現動畫-------
            return this.css({
                left: 0,
                position: position,
                visibility: 'visible',
                overflow: 'auto'
            }).animate({ top: -height }, speed, null, callback);
        };

        $.fn.slideRight = function (speed, callback) {
            //獲取元素position
            var position = this.css('position');
            this.show().css({
                position: 'absolute',
                visibility: 'hidden'
            });
            $('html,body').css({
                overflow: 'hidden',
                height: '100%'
            });
            //獲取元素寬度
            var width = this.width() === 0 ? $(window).width() : this.width();

            //-------經過伸縮元素寬度實現動畫-------
            //return this.css({
            //    top: $(window).scrollTop(),
            //    width: 0,
            //    position: position,
            //    visibility: 'visible',
            //    overflow: 'auto'
            //}).animate({ width: width }, speed, null, callback);

            //-------經過移動元素相對位置實現動畫-------
            return this.css({
                top: $(window).scrollTop(),
                left: -width,
                position: position,
                visibility: 'visible',
                overflow: 'auto',
            }).animate({ left: 0 }, speed, null, callback);
        };

        $.fn.slideLeft = function (speed, callback) {
            //獲取元素position
            var position = this.css('position');
            this.show().css({
                position: 'absolute',
                visibility: 'hidden'
            });
            $('html,body').css({
                overflow: '',
                height: ''
            });
            //獲取元素寬度
            var width = this.width();
            //-------經過伸縮元素寬度實現動畫-------
            //return this.css({
            //    top: 0,
            //    position: position,
            //    visibility: 'visible',
            //    overflow: 'auto'
            //}).animate({ width: 0 }, speed, null, callback);

            //-------經過移動元素相對位置實現動畫-------
            return this.css({
                top: 0,
                position: position,
                visibility: 'visible',
                overflow: 'auto'
            }).animate({ left: -width }, speed, null, callback);
        };
    })(Zepto)
View Code

 

做者:Harry

本文版權歸做者全部,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接.
相關文章
相關標籤/搜索