简体   繁体   中英

Using sprite to create a rotation with Javascript

I'm creating an animation of a ring rotating.

On hover the right rotates 180 degrees, pauses and rotates back to the starting position. If the user removes the cursor off the ring while its animating it needs to reverse from the frame its currently on.

I haven't had much extensive experience with animation in my career as a front end developer so any advice on tech to use would be appreciated.

Currently I'm using CSS Animation with a sprite, as below but it lacks the ability to reverse from the frame it was on when the user leaves the ring.

Here is my working example, It's inspired by http://renren.com/

Example using CSS

 $('body').on('mouseenter', '.item', function() { $(this).removeClass('unactive').addClass('active'); }); $('body').on('mouseleave', '.item', function() { $(this).removeClass('active').addClass('unactive'); }); 
 .content { width: 150px; height: 150px; background-color: #EBEBEB; } .content.ring { background: url(http://a.xnimg.cn/nx/apps/login/cssimg/qrcode1-t.jpg) 0 0 no-repeat } .active .content { background-position: 0 -1800px; -moz-animation: movedown 2000ms steps(12) forwards; -webkit-animation: movedown 2000ms steps(12) forwards } .unactive .content { -moz-animation: moveup 2000ms steps(7) forwards; -webkit-animation: moveup 2000ms steps(7) forwards } @-moz-keyframes movedown { 0% { background-position: 0 0 } 100% { background-position: 0 -1800px } } @-moz-keyframes moveup { 0% { background-position: 0 -1800px } 100% { background-position: 0 -2850px } } @-webkit-keyframes movedown { 0% { background-position: 0 0 } 100% { background-position: 0 -1800px } } @-webkit-keyframes moveup { 0% { background-position: 0 -1800px } 100% { background-position: 0 -2850px } } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> HTML <div class="item active"> <div class="content ring"> </div> </div> 

I've also found plugins like: motio

So my question is, is CSS able to have this much control or would a CANVAS or other jQuery plugin be better suited?

EDIT

I'm still having difficulties figuring this one out although I started writing a script to help control the animation.

I'm trying to control the background position to gain control of the sprite rotating.

Example using Javascript

 ;(function($) { var Ring = function (options) { // context var self = this; // defaults var currFrame = 1, totalFrames, width, height, timeout; // default frame array var framesObj = {}; // option defaults self.class = ""; self.spriteHeight = ""; //properties based on options if (typeof options != 'undefined' && options != undefined && options != null) { self.class = options.class; self.spriteHeight = options.spriteHeight; self.speed = options.speed; } // fire off everything you need self.init = function () { self.buildArr(); } // check for the container dimentions self.frameDimentions = function () { // double check we have a class to select the container with var container = self.class ? true : false; // I know I could just write self.class in the if.. if ( container ) { var container = $("." + self.class + ""); var containerHeight = container.outerHeight(); var containerWidth = container.outerWidth(); return [containerHeight,containerWidth]; } console.log("Please provide a class"); } // calculate frames eg 3000 into 150 per frame is 20.. self.calcFrames = function() { var totalFrames = parseInt(self.spriteHeight) / self.frameDimentions()[0]; return totalFrames; } self.buildArr = function() { // these values need to be pushed in to the arr for (var i = 0; i < self.calcFrames(); i++) { framesObj[(i+1)] = self.frameDimentions()[0]*i; } } self.startForwardAnimation = function(){ // to stop manic clicking../hover.. if( currFrame <= 1 ) { timeout = setInterval( updateFrameForward, self.speed); } } self.startBackwardAnimation = function(){ // to stop manic clicking../hover.. console.log("start backward animation"); if( currFrame != 1 ) { backTimeout = setInterval( updateFrameBackward, self.speed); } } self.stopAnimation = function(){ //currFrame = 1; clearTimeout(timeout); } self.reset = function(){ clearTimeout(timeout); clearTimeout(backTimeout); currFrame = 1; } self.info = function(){ $('.info').html(currFrame); } // if currFrame less than total frames // add one to it // update the current frame variable // stop and clear timer when reach the end function updateFrameForward(){ //check if we are in available frames.. if ( currFrame == self.calcFrames() ) { self.stopAnimation(); self.reset(); } $("." + self.class + "").css({ 'background-position-y': "-" + framesObj[currFrame] + "px" }); self.info(); currFrame = currFrame + 1; } function updateFrameBackward(){ if( currFrame <= 1 ) { self.stopAnimation(); self.reset(); } $("." + self.class + "").css({ 'background-position-y': framesObj[currFrame] + "px" }); self.info(); console.log(currFrame); currFrame = currFrame - 1; } } var ringAniamtion = new Ring({ class: "animate", spriteHeight: "3000", speed: "20" }); $('body').on('mouseenter', '.animate', function(event){ event.preventDefault(); console.log("mouse enter"); ringAniamtion.buildArr(); ringAniamtion.startForwardAnimation(); }); $('body').on('mouseleave', '.animate', function(event){ event.preventDefault(); console.log("mouse leave"); ringAniamtion.stopAnimation(); ringAniamtion.startBackwardAnimation(); }); $('body').on('click', '.stop', function(event){ event.preventDefault(); ringAniamtion.reset(); }); })( jQuery ); // timeout = setTimeout('timeout_trigger()', 3000); // clearTimeout(timeout); 
 .content { width: 150px; height: 150px; background: url(http://a.xnimg.cn/nx/apps/login/cssimg/qrcode1-t.jpg) 0 0 no-repeat; cursor: pointer; } 
 <div class="content animate"> </div> <div class="info"> </div> <a href="" class="stop">stop</a> 

I figured out how to do it in the second code snippet..

;(function($) {

var Ring = function (options) {

    // context
    var self = this; 

    // defaults
    var currFrame = 1, totalFrames, width, height, timeout;

    // default frame array
    var framesObj = {};

    // option defaults
    self.class = ""; 
    self.spriteHeight = ""; 

    //properties based on options
    if (typeof options != 'undefined' && options != undefined && options != null)
    {
        self.class = options.class;
        self.spriteHeight = options.spriteHeight;
        self.speed = options.speed;
    }

    // fire off everything you need
    self.init = function () 
    {
       self.buildArr();
    }

    // check for the container dimentions
    self.frameDimentions = function () 
    {
        // double check we have a class to select the container with
        var container = self.class ? true : false;
        // I know I could just write self.class in the if..
        if ( container )
        {
            var container =  $("." + self.class + "");
            var containerHeight = container.outerHeight();
            var containerWidth = container.outerWidth();
            return [containerHeight,containerWidth];
        }
        console.log("Please provide a class");
    }

    // calculate frames e.g. 3000 into 150 per frame is 20..
    self.calcFrames = function() 
    {
        var totalFrames = parseInt(self.spriteHeight) / self.frameDimentions()[0];
        return totalFrames;
    }

    self.buildArr = function() 
    {
        // these values need to be pushed in to the arr
        for (var i = 0; i < self.calcFrames(); i++) {
            framesObj[(i+1)] = self.frameDimentions()[0]*i;
        }   
    }

    self.startForwardAnimation = function(){
       // to stop manic clicking../hover..
       if( currFrame <= 1 )
       {
           timeout = setInterval( updateFrameForward, self.speed);
       }
    }
    self.startBackwardAnimation = function(){
       // to stop manic clicking../hover..
       console.log("start backward animation");
       if( currFrame != 1 )
       {
           backTimeout = setInterval( updateFrameBackward, self.speed);
       }
    }
    self.stopAnimation = function(){
       //currFrame = 1;
       clearTimeout(timeout);
    }
    self.reset = function(){
       clearTimeout(timeout);
       clearTimeout(backTimeout);
       currFrame = 1;
    }
    self.info = function(){
        $('.info').html(currFrame);
    }

    // if currFrame less than total frames
    // add one to it
    // update the current frame variable
    // stop and clear timer when reach the end
    function updateFrameForward(){
        //check if we are in available frames..
        if ( currFrame == self.calcFrames() )
        {
            self.stopAnimation();
            self.reset();
        }
        $("." + self.class + "").css({
              'background-position-y': "-" + framesObj[currFrame] + "px"
        });
        self.info();
        currFrame = currFrame + 1;
    }
    function updateFrameBackward(){

        if( currFrame <= 1 )
        {
            self.stopAnimation();
            self.reset();
        }
        $("." + self.class + "").css({
              'background-position-y': framesObj[currFrame] + "px"
        });  
        self.info();
        console.log(currFrame);
        currFrame = currFrame - 1;
    }
}

var ringAniamtion = new Ring({
    class: "animate",
    spriteHeight: "3000",
    speed: "20"
});

$('body').on('mouseenter', '.animate', function(event){
    event.preventDefault();
    console.log("mouse enter");
    ringAniamtion.buildArr();
    ringAniamtion.startForwardAnimation();

});

$('body').on('mouseleave', '.animate', function(event){
    event.preventDefault();
    console.log("mouse leave");
    ringAniamtion.stopAnimation();
    ringAniamtion.startBackwardAnimation();
});

$('body').on('click', '.stop', function(event){
    event.preventDefault();
    ringAniamtion.reset();
});

})( jQuery );

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