문제

While looking at this question Set Webkit Keyframes Values Using Javascript Variable The accepted answer is a Webkit specific way to change key-frame CSS dynamically i decided to see if i could change it around so that it would work in Firefox.

I managed to get this working JSFiddle which works as it should except for the fact that sometimes the animation wont start. About 1/4 of clicks will start the animation but the other 3/4 will cause nothing to happen.

Can someone explain to me what exactly is happening? have i missed something simple or is there a race condition somewhere that i am not accounting for?

HTML

<div id="box"></div>

<div id="update-box">Run Another Animation</div>

CSS

@-webkit-keyframes rotate {
    0% {-webkit-transform: rotate(-10deg);}
    100% {-webkit-transform: rotate(10deg);}
}
@keyframes rotate {
    0% {-moz-transform: rotate(-10deg);}
    100% {-moz-transform: rotate(-10deg);}
}
body { text-align: center; }
#box {
        height: 100px;
        width: 100px;
        background-color: blue;
        -webkit-animation-duration: 1s;
        -webkit-animation-timing-function: linear;
        -webkit-animation-name: "rotate";
        animation-duration: 1s;
        animation-timing-function: linear;
        animation-name: "rotate";
        margin: 30px auto;
}

#update-box {
    border: 3px solid black;
    background: #efefef;
    font-weight: bold;
    cursor: pointer;   
    padding: 10px;
    margin: 30px auto;
    display: inline-block;
}
#update-box:hover {
    background: black;
    color: white;
}

JS

// search the CSSOM for a specific -webkit-keyframe rule
function findKeyframesRule(rule) {
    // gather all stylesheets into an array
    var ss = document.styleSheets;

    // loop through the stylesheets
    for (var i = 0; i < ss.length; ++i) {

        // loop through all the rules
        for (var j = 0; j < ss[i].cssRules.length; ++j) {
            // find the -webkit-keyframe rule whose name matches our passed over parameter and return that rule
            if ((ss[i].cssRules[j].type == window.CSSRule.KEYFRAMES_RULE) && ss[i].cssRules[j].name == rule) return [ss[i], ss[i].cssRules[j]];
        }
    }

    // rule not found
    return null;
}

// remove old keyframes and add new ones
function change(anim) {
    // find our -webkit-keyframe rule
    var results = findKeyframesRule(anim);
    var style_sheet = results[0];
    var rule = results[1];
    console.log(rule)
    // remove the existing 0% and 100% rules
    rule.deleteRule("0%");
    rule.deleteRule("100%");
    rule.appendRule("0% { -moz-transform: rotate(0deg);}")
    rule.appendRule("100% { -moz-transform: rotate(" + randomFromTo(-360, 360) + "deg); }")

    // create new 0% and 100% rules with random numbers

    // assign the animation to our element (which will cause the animation to run)
    document.getElementById('box').style.animationName = anim;
}

// begin the new animation process
function startChange() {
    // remove the old animation from our object
    document.getElementById('box').style.animationName = "none";

    // call the change method, which will update the keyframe animation
    setTimeout(function () {
        change("rotate");
    }, 0);
}

// get a random number integer between two low/high extremes
function randomFromTo(from, to) {
    return Math.floor(Math.random() * (to - from + 1) + from);
}

$(function () {
    $('#update-box').bind('click', click_handler);
});

function click_handler(e) {
    e.preventDefault();
    startChange();
}
도움이 되었습니까?

해결책

Turns out it was a refresh issue

// search the CSSOM for a specific -webkit-keyframe rule
function findKeyframesRule(rule) {
    // gather all stylesheets into an array
    var ss = document.styleSheets;

    // loop through the stylesheets
    for (var i = 0; i < ss.length; ++i) {

        // loop through all the rules
        for (var j = 0; j < ss[i].cssRules.length; ++j) {
            // find the -webkit-keyframe rule whose name matches our passed over parameter and return that rule
            if ((ss[i].cssRules[j].type == window.CSSRule.KEYFRAMES_RULE) && ss[i].cssRules[j].name == rule) return [ss[i], ss[i].cssRules[j]];
        }
    }

    // rule not found
    return null;
}

// remove old keyframes and add new ones
function change(anim) {
    // find our -webkit-keyframe rule
    var results = findKeyframesRule(anim);
    var style_sheet = results[0];
    var rule = results[1];
    console.log(rule)
    // remove the existing 0% and 100% rules
    rule.deleteRule("0%");
    rule.deleteRule("100%");
    rule.appendRule("0% { transform: rotate(0deg);}")
    rule.appendRule("100% { transform: rotate(" + randomFromTo(-360, 360) + "deg); }")

    // create new 0% and 100% rules with random numbers
    var box = document.getElementById('box');
    // assign the animation to our element (which will cause the animation to run)
    box.style.animationName = 'none';
    box.offsetWidth = box.offsetWidth;
    box.style.animationName = anim;
}

// begin the new animation process
function startChange() {
    change("rotate");
}

// get a random number integer between two low/high extremes
function randomFromTo(from, to) {
    return Math.floor(Math.random() * (to - from + 1) + from);
}

$(function () {
    $('#update-box').bind('click', click_handler);
});

function click_handler(e) {
    e.preventDefault();
    startChange();
}

Is the updated working code.

http://jsfiddle.net/RHhBz/675/

The following being the important change

box.style.animationName = 'none';
box.offsetWidth = box.offsetWidth; //This line here is needed to force refresh
box.style.animationName = anim;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top