Chrome奇怪的(鳞片)转换行为



所以我一直在开发一个基于CSS过渡的轻量级插件。它能够动态地添加内联样式(过渡)。

插件代码的某些部分(如前缀CSS属性)被删除,使事情更清楚:

(function($, window, document) {
    'use strict';
    var plugin   = 'transition';
    // Constructors
    function Transition(element, animation, options) {
        this.element   = element;
        this.animation = animation;
        this.direction = null;
        this.settings  = $.extend({}, $.fn[plugin].defaults, options);
        this.init();
    }
    // Instance
    $.extend(Transition.prototype, {
        init: function() {
            var instance = this;
          
            instance.direction = $(instance.element).is(':visible') ? // toggle
                'outward':
                'inward' ;
            setTimeout(function() { // separate queue entry to make sure previous re-draw events are finished
                instance.settings.animations.hasOwnProperty(instance.animation) ?
                    instance.start():
                    console.error('Trying to call an undefined animation');
            }, 0);
        },
        /**
         * Start the transition.
         */
        start: function() {
            var instance  = this,
                $element  = $(instance.element);
            // Bind handlers
            $element
                .one('transitionstart', function() {
                    instance.settings.onStart.call($element);
                })
                .one('transitionend', function() {
                    instance.end();
                });
            // Add inline styles
            $element
                .css(instance.style('start'))
                .show() // ensure the element is visible
                .css(instance.style('end'));
        },
        /**
         * End the transition.
         */
        end: function() {
            var instance  = this,
                $element  = $(instance.element);
            instance.direction == 'inward' ?
                $element.show():
                $element.hide();
            instance.settings.onEnd.call($element);
            $element.css({
                opacity: '',
                transform: '',
                transformOrigin: '',
                transition: ''
            }).dequeue();
        },
        /**
         * Get the inline style for the transition.
         *
         * @param state
         */
        style: function(state) {
            var instance  = this,
                animation = instance.settings.animations[instance.animation],
                direction = instance.direction,
                css       = {};
            if (state === 'start') {
                css = (direction == 'inward') ?
                    animation.start:
                    animation.end; // reversed
                css['transition'] = 'all ' + 
                    instance.settings.duration + 'ms ' + 
                    instance.settings.curve + ' ' + 
                    instance.settings.delay + 'ms';
            } else {
                css = (direction == 'inward') ?
                    animation.end:
                    animation.start; // reversed
            }
            
            return css;
        }
    });
    // Plugin definition
    $.fn[plugin] = function(animation, options) {
        return this.each(function() {
            $(this).queue(function() {
                new Transition(this, animation, options);
            });
        });
    };
    // Default settings
    $.fn[plugin].defaults = {
        duration : 500,
        delay    : 0,
        curve    : 'ease',
        onStart  : function() {},
        onEnd    : function() {}
    };
    $.fn[plugin].defaults.animations = {
        fade: {
            start : { 'opacity': 0 },
            end   : { 'opacity': 1 }
        },
        scale: {
            start : { 'opacity': 0, 'transform': 'scale(0.8)' },
            end   : { 'opacity': 1, 'transform': 'scale(1.0)' }
        },
        slide: {
            start : { 'opacity': 0, 'transform': 'scaleY(0)', 'transform-origin': 'bottom'},
            end   : { 'opacity': 1, 'transform': 'scaleY(1)', 'transform-origin': 'bottom'}
        }
    };
})(jQuery, window, document);
$('#fading').transition('fade', {duration: 1000, delay: 1000});
$('#scaling').transition('scale', {duration: 1000, delay: 1000});
$('#sliding').transition('slide', {duration: 1000, delay: 1000});
div {
  display: inline-block;
  margin-bottom: 1em;
  padding: 3em 2em;
  background-color: #EEE;
  border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="fading">Fading block</div>
<div id="scaling">Scaling block</div>
<div id="sliding">Sliding block</div>

由于某些原因,滑动动画在Chrome上不起作用,元素只是淡入/淡出。FireFox和Edge没有这个问题。

应用于滑动动画的CSS:

slide: {
    start : { 'opacity': 0, 'transform': 'scaleY(0)', 'transform-origin': 'bottom'},
    end   : { 'opacity': 1, 'transform': 'scaleY(1)', 'transform-origin': 'bottom'}
}

希望任何魔术师都能弄清楚这是怎么回事。

这是一个已知的转换比例(0)的bug。只需将其更改为缩放(0.01)。

(function($, window, document) {
  'use strict';
  var plugin = 'transition';
  // Constructors
  function Transition(element, animation, options) {
    this.element = element;
    this.animation = animation;
    this.direction = null;
    this.settings = $.extend({}, $.fn[plugin].defaults, options);
    this.init();
  }
  // Instance
  $.extend(Transition.prototype, {
    init: function() {
      var instance = this;
      instance.direction = $(instance.element).is(':visible') ? // toggle
        'outward' :
        'inward';
      setTimeout(function() { // separate queue entry to make sure previous re-draw events are finished
        instance.settings.animations.hasOwnProperty(instance.animation) ?
          instance.start() :
          console.error('Trying to call an undefined animation');
      }, 0);
    },
    /**
     * Start the transition.
     */
    start: function() {
      var instance = this,
        $element = $(instance.element);
      // Bind handlers
      $element
        .one('transitionstart', function() {
          instance.settings.onStart.call($element);
        })
        .one('transitionend', function() {
          instance.end();
        });
      // Add inline styles
      $element
        .css(instance.style('start'))
        .show() // ensure the element is visible
        .css(instance.style('end'));
    },
    /**
     * End the transition.
     */
    end: function() {
      var instance = this,
        $element = $(instance.element);
      instance.direction == 'inward' ?
        $element.show() :
        $element.hide();
      instance.settings.onEnd.call($element);
      $element.css({
        opacity: '',
        transform: '',
        transformOrigin: '',
        transition: ''
      }).dequeue();
    },
    /**
     * Get the inline style for the transition.
     *
     * @param state
     */
    style: function(state) {
      var instance = this,
        animation = instance.settings.animations[instance.animation],
        direction = instance.direction,
        css = {};
      if (state === 'start') {
        css = (direction == 'inward') ?
          animation.start :
          animation.end; // reversed
        css['transition'] = 'all ' +
          instance.settings.duration + 'ms ' +
          instance.settings.curve + ' ' +
          instance.settings.delay + 'ms';
      } else {
        css = (direction == 'inward') ?
          animation.end :
          animation.start; // reversed
      }
      return css;
    }
  });
  // Plugin definition
  $.fn[plugin] = function(animation, options) {
    return this.each(function() {
      $(this).queue(function() {
        new Transition(this, animation, options);
      });
    });
  };
  // Default settings
  $.fn[plugin].defaults = {
    duration: 500,
    delay: 0,
    curve: 'ease',
    onStart: function() {},
    onEnd: function() {}
  };
  $.fn[plugin].defaults.animations = {
    fade: {
      start: {
        'opacity': 0
      },
      end: {
        'opacity': 1
      }
    },
    scale: {
      start: {
        'opacity': 0,
        'transform': 'scale(0.8)'
      },
      end: {
        'opacity': 1,
        'transform': 'scale(1.0)'
      }
    },
    slide: {
      start: {
        'opacity': 0.5,
        'transform': 'scaleY(0.01)',
        'transform-origin': 'bottom'
      },
      end: {
        'opacity': 1,
        'transform': 'scaleY(1)',
        'transform-origin': 'bottom'
      }
    }
  };
})(jQuery, window, document);
$('#fading').transition('fade', {
  duration: 1000,
  delay: 1000
});
$('#scaling').transition('scale', {
  duration: 1000,
  delay: 1000
});
$('#sliding').transition('slide', {
  duration: 1000,
  delay: 1000
});
div {
  display: inline-block;
  margin-bottom: 1em;
  padding: 3em 2em;
  background-color: #EEE;
  border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="fading">Fading block</div>
<div id="scaling">Scaling block</div>
<div id="sliding">Sliding block</div>

相关内容

  • 没有找到相关文章

最新更新