How can I get jquery to execute animations in exact parallel?

前端 未结 7 1944
梦谈多话
梦谈多话 2020-12-09 00:30

I\'m trying to create an accordion widget in jquery similar to jquery\'s accordion plugin, with the difference that I want the handles to appear below their respective conte

7条回答
  •  遥遥无期
    2020-12-09 01:01

    Thanks Adam Plumb for a really great solution to parallel animations. I had a small problem with it though and that was that it somehow saved roles from earlier animations i fixed that by setting the rules to {} before adding them in the init function. It can probably be done in a better way though. I also added a callback function that is called when the animation have finished.

    ParallelAnimations = function(animations, opts){
        this.init(animations, opts);
    };
    
    $.extend(ParallelAnimations.prototype, {
        options: {
            duration: 250,
            callback: null
        },
        rules: {},
    
        init: function(animations, opts){
            // Overwrite the default options
            $.extend(this.options, opts);
    
            // Create a set of rules to follow in our animation
            this.rules = {}; // Empty the rules.
            for(var i in animations){
                this.rules[i] = {
                    element: animations[i].element,
                    changes: new Array()
                };
    
                for(var style in animations[i].styles){
    
                    // Calculate the start and end point values for the given style change
                    var from = this.parse_style_value(animations[i].element, style, "");
                    var to = this.parse_style_value(animations[i].element, style, animations[i].styles[style]);
    
                    this.rules[i].changes.push({
                        from: from,
                        to: to,
                        style: style
                    });
                }
            }
    
            this.start()
        },
    
        /*
         * Does some parsing of the given and real style values
         * Allows for pixel and percentage-based animations
         */
        parse_style_value: function(element, style, given_value){
            var real_value = element.css(style);
    
            if(given_value.indexOf("px") != -1){
                return {
                    amount: given_value.substring(0, (given_value.length - 2)),
                    unit: "px"
                };
            }
    
            if(real_value == "auto"){
                return {
                    amount: 0,
                    unit: "px"
                };
            }
    
            if(given_value.indexOf("%") != -1){
                var fraction = given_value.substring(0, given_value.length - 1) / 100;
    
                return {
                    amount: (real_value.substring(0, real_value.length - 2) * fraction),
                    unit: "px"
                };
            }
    
            if(!given_value){
                return {
                    amount: real_value.substring(0, real_value.length - 2),
                    unit: "px"
                };
            }
        },
    
        /*
         * Start the animation
         */
        start: function(){
            var self = this;
            var start_time = new Date().getTime();
            var freq = (1 / this.options.duration);
    
            var interval = setInterval(function(){
                var elapsed_time = new Date().getTime() - start_time;
    
                if(elapsed_time < self.options.duration){
                    var f = elapsed_time * freq;
    
                    for(var i in self.rules){
                        for(var j in self.rules[i].changes){
                            self.step(self.rules[i].element, self.rules[i].changes[j], f);
                        }
                    }
                }
                else{
                    clearInterval(interval);
    
                    for(var i in self.rules){
                        for(var j in self.rules[i].changes)
                            self.step(self.rules[i].element, self.rules[i].changes[j], 1);
                    }
                    if(self.options.callback != null) {
                        self.options.callback(); // Do Callback
                    }
                }
            }, 10);
        },
    
        /*
         * Perform an animation step
         * Only works with position-based animations
         */ 
        step: function(element, change, fraction){
    
            var new_value;
            switch(change.style){
                case 'height':
                case 'width':
                case 'top':
                case 'bottom':
                case 'left':
                case 'right':
                case 'marginTop':
                case 'marginBottom':
                case 'marginLeft':
                case 'marginRight':
                    new_value = Math.round(change.from.amount - (fraction * (change.from.amount - change.to.amount))) + change.to.unit;
                    break;
            }
    
            if(new_value)
                element.css(change.style, new_value);
        }
    });
    

提交回复
热议问题