简体   繁体   中英

Simultaneous custom animation using CSS 3 and jQuery

I am new to jQuery and CSS 3 and have been digging up CSS 3 a lot in my free time. I have this small testimonials animation that I would really like to work in a certain way, but unfortunately I am unable to get the CSS and jQuery to behave exactly as I want it to.

Here's what I have done so far: Fiddle .

What I want to achieve:

Now when I click on the <li> , what I basically want is the current text in the <div class="says"></div> to move downwards and the new text (basically text stored in the data-says on the clicked li) to transition in. Both of this should happen simultaneously.

My code so far looks like this, CSS:

// custom animation for sliding in new content
keyframes rotate{
    0%{
        transform:rotateX(20deg) translateY(-20px);
        /*transform: translateX(100px);*/
        text-shadow:1px 1px 1px rgba(0,0,0,.5),
                    1px 1px 2px rgba(0,0,0,.5);;
    }
    100%{
        transform:rotateX(0deg) translateX(0px);
        text-shadow:none;
    }
}

.animated{
    -webkit-animation-name: rotate;
    -o-animation-name: rotate;
    animation-name: rotate;
    -webkit-animation-duration: 1.35s;
    -o-animation-duration: 1.35s;
    animation-duration: 1.35s;
}

// custome animation for downward slide 
@keyframes movedown{
    0%{
        transform:rotateX(0) translateY(0);
    }
    100%{
        transform:rotateX(-30deg) translateY(20px);
    }
} 


.moved{
    -webkit-animation-name: movedown;
    -o-animation-name: movedown;
    animation-name: movedown;
    -webkit-animation-duration: 1s;
    -o-animation-duration: 1s;
    animation-duration: 1s;
}

Now the jQuery code:

$(document).ready(function () {
                $('ul').on('click', 'li', function () {

                    $('.says').removeClass('moved animated');

                    setTimeout(function(){
                        $('.says').addClass('moved');
                        setTimeout(function(){
                            // $('.says').html('')
                        }, 1500)    
                    }, 100);

                    $this = $(this);

                    setTimeout(function(){
                        var _stor = $this.data('says');
                        $('.says').removeClass('animated');
                        setTimeout(function(){
                            $('.says') .html(_stor).addClass('animated');
                        },100)

                    }, 700)

                });
            });

Basically in the jQuery code I am attaching a eventhandler to the <ul> tag and after that I am basically targeting the <div class="say"></div> to remove and update the content, but notice 1 things.

The two setTimeout function (forget the internal setTimeout function), both function separately, ie. the 1st setTimeout function removes the current text from the div with a transition and then the 2nd setTimeout function transitions the new text, but both functions are functioning separately rather then simultaneously. I have no idea how I can get these two transitions to work simultaneously.

By simultaneously, I mean the following:

同步动画

I'm going to cover a few topics in response - for posterity, and hopefully some educational benefit - before actually pulling this together in an example that fits the specific needs of your post.

Simultaneous Execution of JavaScript & jQuery functions

Technically, it's not possible to execute JavaScript functions simultaneously - or asynchronously. All JavaScript code is executed in on a single thread in an event loop . However, it is possible to queue up actions that won't take place until after the event loop is available again.

Code Snippet Example :

 /// Open your console and then click "Run" within jsFiddle // Illustration of how the 'event loop' handles executing functions $(document).ready(function() { console.log("starting..."); setTimeout(runAsync, 0); //Async? console.log("ending...") }); function runAsync() { console.log("...running Async... now!"); } //"starting..." //"ending..." //"...running Async... now!"
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

It's not really async - rather deferred execution. Deferring can be used, however, in conjunction with css to give the appearance of simultaneous actions occurring.

Mocking Simultaneous Execution of Functions With JQuery

A very easy way to create the appearance of simultaneous functions is through the use of JQuery's .animate() . Since, part of the goal of the OP was to utilize CSS3 (and to learn while solving a problem) - an example that leans more on css, less on .animate() , and actually answers the OP is included later. In the meantime, here is a "simultaneous" example using .animate() :

JQuery .animate() Example :

 $(function() { $("#go").click(function() { console.log("--- START ---"); console.log("Animate One..."); $("#one").animate({ left: "+=300", top: "+=300", opacity: 0.25 }, "slow", function() { // <-- callback console.log("Animate One Callback..."); }); console.log("Animate Two..."); $("#two").animate({ left: "+=10", top: "+=20", fontSize: "50px" }, "slow", function() { // <-- callback console.log("Animate Two Callback..."); }); }); }); // --- START --- // Animate One... // Animate Two... // Animate One Callback... // Animate Two Callback...
 #go { margin: 10px; height: 30px; width: 100px; } .cont { position: relative; height: 800px; width: 800px; background-color: grey; } #one { position: absolute; height: 200px; width: 200px; background-color: red; } #two { position: absolute; height: 100px; width: 100px; background-color: black; color: white; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <button id="go">GO</button> <div class="cont"> <div id="one">One</div> <div id="two">Two</div> </div>

You'll notice from the console log that the .animate() callback functions were delegated to the end of the event loop - similar to setTimeout() .

There's also another useful jQuery function, .queue() , that allows you to manipulate the event loop. Combined with the CSS3 being utilized in the OP, .queue() offers a slightly cleaner alternative to setTimeout() that also enables you to give the appearance of simultaneous functions.

ANSWER(!!!): Using jQuery .queue() and CSS3 Instead of jQuery .animate()

Please see comments in code:

 $(document).ready(function() { $('ul').on('click', 'li', function() { // Get the current visible element var curElem = $('.content'); // Reset the class assignment if not first time li is clicked curElem.removeClass('moved animated'); // Clone the original element, set it to "no display" // Make sure it's behind the original when both visible var cloneElem = curElem.clone(); cloneElem.css({ "z-index": "-1", "display": "none" }); // Get new text for Clone // Fill the Clone with text, add it to the container div $this = $(this); var _stor = $this.data('says'); cloneElem.find('.says').html(_stor); cloneElem.appendTo('#info-container'); // Queue and delay functions similarly to setInterval - but is // slightly easier to read/write/comprehend // fiddling with the "delay" and "fade" function numbers will change effect curElem.addClass('moved').delay(1500).queue(function() { $(this).fadeOut(800).remove().dequeue(); // Remove original element }); cloneElem.addClass('animated').delay(100).queue(function() { $(this).fadeIn(200).css("z-index", "").dequeue(); }); }); });
 /* ~~~ START additional styles ~~~ */ /* ADDED - needed parent element with relative positioning in order for child element to move as expected */ #info-container { border: solid 2px black; overflow: hidden; display: block; position: relative; min-height: 250px; z-index: -2; } /* ADDED - basically .says but with asbolute positioning */ .content { position: absolute; max-width: 800px; margin-left: -400px; text-align: justify; background-color: #fff; top: 25%; left: 50%; } /* Also changed later -- translateY() in movedown, rotate was difficult to see "simultaneous" effect without - please tweak if needed */ /* ~~~ END addtional styles ~~*/ .clearfix:before, .clearfix:after { content: ''; display: table; } .clearfix:after { clear: both; } img { max-height: 36px; max-width: hidden; } /*styles for link-holder*/ .link-holder { list-style: none; padding: 0; margin: 0; } .link-holder li { cursor: pointer; float: left; width: 25%; display: table; text-align: left; } .link-holder li img { display: table-cell; vertical-align: middle; display: block; margin-right: auto; margin-left: auto; } .link-holder li p { display: table-cell; vertical-align: middle; } .link-holder li p { margin: 0 0 0px 0; } /* end of styles for link-holder*/ /*animation styles*/ @-webkit-keyframes rotate { 0% { transform: rotateX(20deg) translateY(-150px); /*transform: rotateX(20deg) translateY(-20px);*/ /* <--- INCREASE translateY to make scroll in effects more prounouced" /*transform: translateX(100px);*/ text-shadow: 1px 1px 1px rgba(0, 0, 0, .5), 1px 1px 2px rgba(0, 0, 0, .5); ; } 100% { transform: rotateX(0deg) translateX(0px); text-shadow: none; } } @-webkit-keyframes movedown { 0% { transform: rotateX(0) translateY(0); } 100% { transform: rotateX(-10deg) translateY(150px); /* transform: rotateX(-10deg) translateY(20px);*/ /* <---- INCREASE translateY to make "scroll out effect" more pronounced */ } } .moved { -webkit-animation-name: movedown; -o-animation-name: movedown; animation-name: movedown; -webkit-animation-duration: 1s; -o-animation-duration: 1s; animation-duration: 1s; } .animated { -webkit-animation-name: rotate; -o-animation-name: rotate; animation-name: rotate; -webkit-animation-duration: 1.35s; -o-animation-duration: 1.35s; animation-duration: 1.35s; -webkit-transition-timing-function: cubic-bezier(0.450, 0.395, 0.220, 1); /* older webkit */ -webkit-transition-timing-function: cubic-bezier(0.450, 0.395, 0.220, 1.210); -moz-transition-timing-function: cubic-bezier(0.450, 0.395, 0.220, 1.210); -o-transition-timing-function: cubic-bezier(0.450, 0.395, 0.220, 1.210); transition-timing-function: cubic-bezier(0.450, 0.395, 0.220, 1.210); /* custom */ } /*end of animation styles*/
 <!-- ADDED: two divs - info-container, content the 'says' <p> in the OP was doing double duty, holding association to css formatting and containing text to be replaced added two container divs to make it easier to copy / swap out without breaking the css !--> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <section id="testimonials" class="testimo"> <div> <div id="info-container"> <div class="content"> <p class="says">stock ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> </div> </div> <ul class="link-holder clearfix"> <li data-says="stock ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."> <img src="http://www.wpclipart.com/blanks/buttons/round/button_round_seagreen.png" alt=""> <p>Lorem Ipsum <br><small>Stock Broker</small> </p> </li> <li data-says="Angel ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."> <img src="http://www.wpclipart.com/blanks/buttons/round/button_round_seagreen.png" alt=""> <p>Lorem Ipsum <br><small>Angel investor</small> </p> </li> <li data-says="Client ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."> <img src="http://www.wpclipart.com/blanks/buttons/round/button_round_seagreen.png" alt=""> <p>Lorem Ipsum <br><small>Client</small> </p> </li> <li data-says="Developer ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."> <img src="http://www.wpclipart.com/blanks/buttons/round/button_round_seagreen.png" alt=""> <p>Lorem Ipsum <br><small>Developer</small> </p> </li> </ul> </div> </section>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM