2017-12-08 1 views
2

Wie kann ich die Dauer eines Übergangs/einer Animation auf Pixel pro Sekunde einstellen?Javascript/CSS - Animationsdauer in Pixel pro Sekunde

Sie sehen die zwei verschiedenen Wrapper mit einer unterschiedlichen Gesamthöhe, abhängig vom farbigen Inhalt. Die Gesamtgeschwindigkeit ist die gleiche, die vom css transition Attribut angegeben wird, das ist in Ordnung, wenn Sie mehrere Animationen mit der gleichen Dauer möchten. Für ein glatteres Aussehen möchte ich diesen Übergangs-/Animationseffekt auf Pixel pro Sekunde einstellen, so dass es dort so viele Pixel dauert. Mehr Inhalt = mehr Pixel = längere Animation.

Wie kann ich dies mit Vanille Javascript oder sogar CSS erreichen?

var wrapper1 = document.getElementById('wrapper1'); 
 
var wrapper2 = document.getElementById('wrapper2'); 
 
var header1 = document.getElementById('header1'); 
 
var header2 = document.getElementById('header2'); 
 
var wrapper1CmputedHeight = wrapper1.scrollHeight; 
 
var wrapper2CmputedHeight = wrapper2.scrollHeight; 
 

 
header1.addEventListener('click', function() { 
 
    if (wrapper1.style.height === '60px') { 
 
    wrapper1.style.height = wrapper1CmputedHeight + 'px'; 
 
    } else { 
 
    wrapper1.style.height = '60px'; 
 
    } 
 
}) 
 

 
header2.addEventListener('click', function() { 
 
    if (wrapper2.style.height === '60px') { 
 
    wrapper2.style.height = wrapper2CmputedHeight + 'px'; 
 
    } else { 
 
    wrapper2.style.height = '60px'; 
 
    } 
 
})
#wrapper1, 
 
#wrapper2 { 
 
    background: #fff; 
 
    border: 1px solid grey; 
 
    overflow: hidden; 
 
    transition: height .2s linear 
 
} 
 

 
#wrapper1 { 
 
    margin-bottom: 40px 
 
} 
 

 
#header1, 
 
#header2 { 
 
    height: 60px; 
 
    display: flex; 
 
    align-items: center; 
 
    justify-content: center; 
 
    cursor: pointer 
 
} 
 

 
#content1 { 
 
    height: 20px; 
 
    background: blue 
 
} 
 

 
#content2 { 
 
    height: 600px; 
 
    background: green 
 
}
<div id="wrapper1" style="height: 60px"> 
 
    <div id="header1"> 
 
    <span>header</span> 
 
    </div> 
 
    <div id="content1"></div> 
 
</div> 
 

 
<div id="wrapper2" style="height: 60px"> 
 
    <div id="header2"> 
 
    <span>header</span> 
 
    </div> 
 
    <div id="content2"></div> 
 
</div>

Antwort

2

Die einzige Möglichkeit, dies mit CSS-Übergängen zu tun, ist dynamisch die Dauer des Übergangs zu berechnen ein wenig Javascript. Also, in Ihrem Code würde ich die Dauer für die Übergangsregel in Ihrem CSS entfernen, ich, e.

#wrapper1, 
#wrapper2 { 
    background: #fff; 
    overflow: hidden; 
    transition: height linear 
} 

und ich würde stattdessen die Dauer in den Klick-Handler wie folgt festgelegt:

header1.addEventListener('click', function() { 
    if(wrapper1.style.height === '60px') { 
    wrapper1.style.height = wrapper1CmputedHeight + 'px'; 
    wrapper1.style.transitionDuration=(wrapper1CmputedHeight/100)+"s"; 
    } else { 
    wrapper1.style.height = '60px'; 
    } 
}) 

Also in diesem Fall, ich habe eine Geschwindigkeit von 100 Pixel pro Sekunde (dies ist der /100 Teil in der obige Code).

+0

Nicht so schwierig! Sauber und einfach, großartig! Was mache ich, wenn ich verschiedene Attribute wie "transition: height linear, width .1s linear (immer fixed), opacity .2s linear (fixed too)" habe? Wie kann ich nur die Dauer für die Eigenschaft height bearbeiten? – Flo

+0

In diesem Fall könnten Sie für die Übergangsdauer eine durch Kommas getrennte Liste von Werten angeben, einen Wert für jede Eigenschaft, zB: 'wrapper1.style.transitionDuration = '0.3s, 0.1s, 0.1s'' und die Dauer entfernen von "Übergang". Alternativ ist es möglich, einige zusätzliche Wrapper hinzuzufügen und die anderen Übergänge auf diese Wrapper anzuwenden. – redneb

+0

Die Lösung mit mehreren Dauern ist nett, ich werde das versuchen! Wie kann ich diese berechnete Dauer in einer Verzögerungsfunktion weiter verwenden? Im Normalfall gibt man einfach den Millisekunden-Wert ein, ich habe versucht, es wie im Beispiel "(wrapper1CmputedHeight/100)" einzufügen, aber es funktioniert nicht. Weißt du wie das geht? – Flo

0

fand ich diese example here aber es scheint, den Trick für Sie zu tun (nach einigen Optimierungen). In diesem Fall wird eine Quartz-Interpolation implementiert, Sie können diesen Algorithmus jedoch auf Linear/Andere einstellen, falls dies gewünscht wird.

// 
 
// Animate 
 
// 
 
var btn1 = document.querySelector('.animate'); 
 
btn1.addEventListener('click', function() { 
 
    reset(); 
 
    animate(); 
 
    btn1.disabled = true; 
 
}); 
 

 
// 
 
// http://easings.net/#easeInOutQuart 
 
// t: current time 
 
// b: beginning value 
 
// c: change in value 
 
// d: duration 
 
// 
 
function easeInOutQuart(t, b, c, d) { 
 
    if ((t /= d/2) < 1) return c/2 * t * t * t * t + b; 
 
    return -c/2 * ((t -= 2) * t * t * t - 2) + b; 
 
} 
 

 
function reset() { 
 
    document.querySelector('.square').style.width = Math.floor((Math.random() * 500) + 1) + "px"; 
 
} 
 

 
function animate() { 
 

 
    var rect = document.querySelector('.square'); 
 
    var from = 0; 
 
    var to = window.getComputedStyle(rect, null).getPropertyValue("width").split('px')[0]; 
 
    var duration = to * 10; 
 

 
    var start = new Date().getTime(); 
 
    var timer = setInterval(function() { 
 
    var time = new Date().getTime() - start; 
 
    var width = easeInOutQuart(time, from, to - from, duration); 
 
    rect.style.width = width + "px"; 
 
    if (time >= duration) { 
 
     clearInterval(timer); 
 
     btn1.disabled = false; 
 
    } 
 
    }, 1000/60); 
 
    rect.style.width = from; 
 
} 
 

 
reset();
.square { 
 
    position: relative; 
 
    display: block; 
 
    width: 30px; 
 
    height: 30px; 
 
    background-color: #f00; 
 
}
<div class="square"></div> 
 

 
<button class="animate">Animate</button>