어떻게 받을 수 있 jquery 를 실행하는 애니메이션에서 정확한 병렬?

StackOverflow https://stackoverflow.com/questions/811750

  •  03-07-2019
  •  | 
  •  

문제

내가 만들려고 아코디언 위젯에서 jquery 유사한 jquery 아코디언의 플러그인, 으로,차이 내가 원하는 핸들을 아래 표시됩 해당 콘텐츠의 대상입니다.내 아코디언은 작품을 감소하여 높이의 콘텐츠 섹션에 동시에 증가하는 고도의 클릭한 콘텐츠 섹션입니다.나는 예를 게시 .내 문제의 애니메이션이지에서 시작 정확히 동일한 시간,그리고 눈에 띄는"뛰어"인해 약간의 지연전에는 두 번째는 애니메이션이 시작됩니다.

Scriptaculous 기능을 갖는 불 효과가 있다.Parallel 할 수 있는 배열을 만들의 애니메이션 효과 및 실행에서 그들을 병행합니다.불행하게도,나는 찾을 수 없는 것과 비슷한 jquery.

이 있습 방법을 실행할 수 있는 정확한 병렬 애니메이션에서 별도의 div 에 jquery?

편집:나라에서 많은 관심의 다른 방법은 코딩이 아코디언 위젯입니다.그래서가 있다면 다른 어떤 방법을 사람들이 생각하는 것이 작업 난 열린다.

도움이 되었습니까?

해결책

하나 더 많은 대답은,희망이 나의 마지막 중 하나...

불행하게도,존 레식의 syncAnimate 방법는 코담배에 대한 아코디언 형식 애니메이션이 이야기를 준비했습니다.는 동안 그것은 좋은 작품에 Firefox,게 작업을 원활하게 즉 또는 사파리 등이 있습니다.

는다고 말했고,내가 결정해 탄알을 물고 쓰는 내 자신의 애니메이션 엔진 않는 간단한 병렬 애니메이션이 있습니다.클래스 코드를 사용 jquery 기능을 하지만 jquery 플러그인입니다.또한,나는 설정을 하기/position 애니메이션,모두 필요합니다.

ParallelAnimations = function(animations, opts){
    this.init(animations, opts);
};

$.extend(ParallelAnimations.prototype, {
    options: {
        duration: 250
    },
    rules: {},

    init: function(animations, opts){
        // Overwrite the default options
        $.extend(this.options, opts);

        // Create a set of rules to follow in our animation
        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);
                }
            }
        }, 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);
    }
});

원래 아코디언 클래스만을 수정해야에서 애니메이션 방법을 사용하는 새로운 호출합니다.

Accordion = function(container_id, options){
    this.init(container_id, options);
}

$.extend(Accordion.prototype, {
    container_id: '',
    options: {},
    active_tab: 0,    
    animating: false,
    button_position: 'below',
    duration: 250,
    height: 100,

    handle_class: ".handle",
    section_class: ".section",

    init: function(container_id, options){
        var self = this;
        this.container_id = container_id;
        this.button_position = this.get_button_position();

        // The height of each section, use the height specified in the stylesheet if possible
        this.height = $(this.container_id + " " + this.section_class).css("height");

        if(options && options.duration)    this.duration = options.duration;
        if(options && options.active_tab)  this.active_tab = options.active_tab;

        // Set the first section to have a height and be "open"
        // All the rest of the sections should have 0px height
        $(this.container_id).children(this.section_class).eq(this.active_tab)
            .addClass("open")
            .css("height", this.height)
            .siblings(this.section_class)
            .css("height", "0px");

        // figure out the state of the handles
        this.do_handle_logic($(this.container_id).children(this.handle_class).eq(this.active_tab));

        // Set up an event handler to animate each section
        $(this.container_id + " " + this.handle_class).mouseover(function(){

            if(self.animating)
                return;

            self.animate($(this));
        });
    },

    /*
     * Determines whether handles are above or below their associated section
     */     
    get_button_position: function(){
        return ($(this.container_id).children(":first").hasClass(this.handle_class) ? 'above' : 'below');
    },

    /*
     * Animate the accordion from one node to another
     */ 
    animate: function(handle){
        var active_section = (this.button_position == 'below' ? handle.prev() : handle.next());    
        var open_section = handle.siblings().andSelf().filter(".open");

        if(active_section.hasClass("open"))
            return;

        this.animating = true;

        // figure out the state of the handles
        this.do_handle_logic(handle);

        // Close the open section
        var arr = new Array();
        arr.push({
            element: open_section,
            styles: {
                "height": "0px"
            }
        });
        arr.push({
            element: active_section,
            styles: {
                "height": this.height
            }
        });
        new ParallelAnimations(arr, {duration: this.duration});

        var self = this;
        window.setTimeout(function(){
            open_section.removeClass("open");
            active_section.addClass("open");
            self.animating = false;
        }, this.duration);
    },

    /*
     * Update the current class or "state" of each handle
     */ 
    do_handle_logic: function(handle){
        var all_handles = handle.siblings(".handle").andSelf();
        var above_handles = handle.prevAll(this.handle_class);
        var below_handles = handle.nextAll(this.handle_class);

        // Remove all obsolete handles
        all_handles
            .removeClass("handle_on_above")
            .removeClass("handle_on_below")
            .removeClass("handle_off_below")
            .removeClass("handle_off_above");

        // Apply the "on" state to the current handle
        if(this.button_position == 'below'){
            handle
                .addClass("handle_on_below");
        }
        else{
            handle
                .addClass("handle_on_above");
        }

        // Apply the off above/below state to the rest of the handles
        above_handles
            .addClass("handle_off_above");

        below_handles
            .addClass("handle_off_below");
    }
});

HTML 은 여전히 동일한 방법:

<html>
<head>
    <title>Parallel Accordion Animation</title>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript" src="ui.js"></script>
    <script type="text/javascript">
    $(document).ready(function(){
        new Accordion("#accordion");
    });
    </script>
    <style type="text/css">
    #accordion{
        position: relative;
    }
    #accordion .handle{
        width: 260px;
        height: 30px;
        background-color: orange;
    }
    #accordion .section{
        width: 260px;
        height: 445px;
        background-color: #a9a9a9;
        overflow: hidden;
        position: relative;
    }
    </style>
</head>
<body>

<div id="accordion">
    <div class="section"><!-- --></div>
    <div class="handle">handle 1</div>
    <div class="section"><!-- --></div>
    <div class="handle">handle 2</div>
    <div class="section"><!-- --></div>
    <div class="handle">handle 3</div>
    <div class="section"><!-- --></div>
    <div class="handle">handle 4</div>
    <div class="section"><!-- --></div>
    <div class="handle">handle 5</div>
</div>

</body>
</html>

거기에 몇 가지 추가 할 수 있습 향후:-대기 중인 애니메이션 -애니메이션을 위한 다른 형태의 스타일(색상,etc.)

다른 팁

John Resig는 게시했습니다 동기화 된 애니메이션 샘플 (지침 없음, 색상 상자를 클릭하십시오). 통제에 적용하는 방법을 알아 내려면 약간의 작업이 필요하지만 시작하기에 좋은 곳이 될 수 있습니다.

이것은 실행되는 애니메이션을 동시에 해결하지는 않지만 지터없이 예상되는 동작을 재현합니다. 애니메이션 수를 줄이기 위해 핸들 내부에 섹션을 배치했습니다. 코드를 더 작게 만들기 위해 andself ()를 사용할 수 있지만 읽기가 더 어려울 수 있습니다. 스타일 조정을해야합니다.

<html>
<head>
    <title>Accordion Test</title>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">

    $(document).ready(function(){
        $("#accordion .handle").click(function(){
            var open = $(this).parent().children(".section, .open");
            var active = $(this);

            if (!active.hasClass("open"))
            {
                if (active.hasClass("up"))
                {
                  console.log("up");
                  active.animate({top:"+=100"}).removeClass("up");
                  active.nextAll(".handle").andSelf().filter(".up").animate({top:"+=100"}).removeClass("up");
                  $(".section", active).slideUp();
                  $(".section", active.nextAll()).slideUp();
                  $(".section", active.prev()).slideDown();
                }
                else
                {
                  active.prevAll(".handle").not(".up").animate({top:"-=100"}).addClass("up");
                  $(".section", active.prev()).slideDown();
                }

                open.removeClass("open");
                active.addClass("open");
            }
        });
    });

    </script>
    <style type="text/css">
        #accordion{
            width: 200px;
            position:relative;
        }
        #accordion .section{
            width: 196px;
            margin-left: 2px;
            height: 100px;
            background-color: #b9b9b9;
            display:none;
        }
        #accordion .handle{
            width: 200px;
            height: 30px;
            background-color: #d9d9d9;
            border: 1px solid black;
            cursor: pointer;
            cursor: hand;
            position: absolute;
        }
        #accordion .handle .header {
            height: 30px;
        }
    </style>
</head>
<body>

<div id="accordion">
    <div id="s1" class="section open" style="display:block">This is section 1</div>

    <div class="handle open" style="top:100;">
      <div class="header">handle 1</div>
      <div class="section">This is section 2</div>
    </div>

    <div class="handle" style="top:130;">
      <div class="header">handle 2</div>
      <div class="section">This is section 3</div>
    </div>

    <div class="handle" style="top:160;">
      <div class="header">handle 3</div>
      <div class="section">This is section 4</div>
    </div>

    <div class="handle" style="top:190;">
      <div class="header">handle 4</div>
      <div class="section">This is section 5</div>
    </div>

    <div class="handle" style="top:220;">
      <div class="content">handle 5</div>
    </div>
</div>

</body>
</html>

병렬 애니메이션에 대한 훌륭한 솔루션에 대해 Adam Plumb에게 감사드립니다. 그래도 작은 문제가 있었지만 이전 애니메이션에서 역할을 저장 한 것이 었습니다.이 기능에 추가하기 전에 규칙을 {}로 설정하여이를 수정했습니다. 그래도 더 나은 방법으로 수행 할 수 있습니다. 또한 애니메이션이 완료되었을 때 호출되는 콜백 함수를 추가했습니다.

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);
    }
});

나는 당신의 문제가 아닙 타이밍 그러나 분수 부문의 픽셀.당신이 시도하는 경우 이 코드는 그 부드러운 손잡이를 위한 1 2 하지만 다른 사람에 Firefox3 그러나 여전히 보이는 불안해합니다.

 active
    .animate({ height: "100px" })
    .siblings(".section")
    .animate({ height: "0px" });

당신에 대해 생각이 만드는 요소들의 위치 정적 또는 절대?하는 경우에만의 위치를 이동하는 두 가지 요소를 걱정할 필요가 없에 대해 다른 사람을 점프.나에게는 두 번째와 수 있도록 노력하겠습니다 예입니다.

업데이트 : 더 이상 John Resig의 동기화 플러그인을 사용하지 않습니다. 최종 솔루션은 나중에 답변을 참조하십시오

프로젝트에 사용하는 최종 작업 솔루션을 제공하고 싶었습니다. 사용합니다 동기화 플러그인 John Resig가 썼다 (Corbin March에 의해 게시 됨).

이 코드는 다음과 같습니다.

  • CSS의 섹션 높이를 읽고 사용하십시오
  • 옵션 객체를 통해 애니메이션 지속 시간을 설정하고 기본 활성 섹션을 설정할 수 있습니다.
  • 섹션에 대한 핸들 위치를 자동으로 감지하고 그에 따라 조정합니다. 따라서 핸들을 마크 업의 섹션 위 또는 아래로 이동하고 JS 코드를 변경할 필요가 없습니다.

HTML

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="ui.js"></script>

<script type="text/javascript">
$(document).ready(function(){
    new Accordion("#accordion", {active_tab: 0});
});
</script>
<style type="text/css">
#accordion .handle{
    width: 260px;
    height: 30px;
    background-color: orange;
}
#accordion .section{
    width: 260px;
    height: 445px;
    background-color: #a9a9a9;
    overflow: hidden;
    position: relative;
}

</style>

<div id="accordion">
    <div class="section">Section Code</div>
    <div class="handle">handle 1</div>

    <div class="section">Section Code</div>
    <div class="handle">handle 2</div>

    <div class="section">Section Code</div>
    <div class="handle">handle 3</div>

    <div class="section">Section Code</div>
    <div class="handle">handle 4</div>

    <div class="section">Section Code</div>
    <div class="handle">handle 5</div>
</div>

ui.js

Accordion = function(container_id, options){
    this.init(container_id, options);
}

$.extend(Accordion.prototype, {
    container_id: '',
    options: {},
    active_tab: 0,    
    animating: false,
    button_position: 'below',
    duration: 250,
    height: 100,

    handle_class: ".handle",
    section_class: ".section",

    init: function(container_id, options){
        var self = this;
        this.container_id = container_id;
        this.button_position = this.get_button_position();

        // The height of each section, use the height specified in the stylesheet if possible
        this.height = $(this.container_id + " " + this.section_class).css("height");

        if(options && options.duration)    this.duration = options.duration;
        if(options && options.active_tab)  this.active_tab = options.active_tab;

        // Set the first section to have a height and be "open"
        // All the rest of the sections should have 0px height
        $(this.container_id).children(this.section_class).eq(this.active_tab)
            .addClass("open")
            .css("height", this.height)
            .siblings(this.section_class)
            .css("height", "0px");

        // figure out the state of the handles
        this.do_handle_logic($(this.container_id).children(this.handle_class).eq(this.active_tab));

        // Set up an event handler to animate each section
        $(this.container_id + " " + this.handle_class).mouseover(function(){

            if(self.animating)
                return;

            self.animate($(this));
        });
    },

    /*
     * Determines whether handles are above or below their associated section
     */     
    get_button_position: function(){
        return ($(this.container_id).children(":first").hasClass(this.handle_class) ? 'above' : 'below');
    },

    /*
     * Animate the accordion from one node to another
     */ 
    animate: function(handle){
        var active_section = (this.button_position == 'below' ? handle.prev() : handle.next());    
        var open_section = handle.siblings().andSelf().filter(".open");

        if(active_section.hasClass("open"))
            return;

        this.animating = true;

        // figure out the state of the handles
        this.do_handle_logic(handle);

        // Close the open section
        open_section
            .syncAnimate(active_section, {"height": "0px"}, {queue:false, duration:this.duration}, '')
            .removeClass("open");

        // Open the new section
        active_section
            .syncAnimate(open_section, {"height": this.height}, {queue:false, duration:this.duration}, '')
            .addClass("open");

        var self = this;
        window.setTimeout(function(){
            self.animating = false;
        }, this.duration);
    },

    /*
     * Update the current class or "state" of each handle
     */ 
    do_handle_logic: function(handle){
        var all_handles = handle.siblings(".handle").andSelf();
        var above_handles = handle.prevAll(this.handle_class);
        var below_handles = handle.nextAll(this.handle_class);

        // Remove all obsolete handles
        all_handles
            .removeClass("handle_on_above")
            .removeClass("handle_on_below")
            .removeClass("handle_off_below")
            .removeClass("handle_off_above");

        // Apply the "on" state to the current handle
        if(this.button_position == 'below'){
            handle
                .addClass("handle_on_below");
        }
        else{
            handle
                .addClass("handle_on_above");
        }

        // Apply the off above/below state to the rest of the handles
        above_handles
            .addClass("handle_off_above");

        below_handles
            .addClass("handle_off_below");
    }
});

적절한 대기열과 범위로 jQuery에서 평행 효과를 할 수 없습니다. Scriptaculous는 반면에 jQuery가 .queue와 .animate가있는 큐와 범위로 바로 그것을 얻었습니다. jQuery가 상자 밖에서 유일하게 좋은 것은 DOM의 스타일 속성을 밀어 넣는 반면, 스크립트는 효과로 가능한 것의 전체 스펙트럼을 다룹니다.

Scriptaculous를 사용해야하며 John Resig는 jquery.fx를 다시 생각해야합니다. 그는 Scripty2.com을 살펴보아야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top