【问题标题】:Chrome weird (scaleY) transition behaviourChrome 奇怪的 (scaleY) 过渡行为
【发布时间】:2017-03-05 12:36:35
【问题描述】:

所以我一直在开发一个基于 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'}
}

希望任何魔术师都能弄清楚发生了什么。

【问题讨论】:

    标签: jquery css google-chrome css-transitions inline-styles


    【解决方案1】:

    这是转换比例(0)的已知错误。只需将其更改为 scale(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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      • 2018-04-20
      • 1970-01-01
      • 2015-11-15
      • 1970-01-01
      • 2012-04-25
      相关资源
      最近更新 更多