wake-up-neo.net

Dynamische Erstellung von "@ -Keyframe" CSS-Animationen

Ich muss ein div drehen und an einer bestimmten Position anhalten (der Wert wird vom Server empfangen).

Ich habe versucht, native JS zu drehen und zu stoppen, aber es beansprucht meine CPU sehr.

Ich kann mit CSS-Animationen drehen, aber ich muss eine Klasse erstellen, die dynamisch beschreibt, wo die Animation angehalten werden soll. So etwas wie 

@-webkit-keyframes spinIt {
    100% {
        -webkit-transform: rotate(A_DYNAMIC_VALUE);
    }
}
@-moz-keyframes spinIt {
    100% {
        -webkit-transform: rotate(A_DYNAMIC_VALUE);
    }
}

Hier ist eine Referenz 

http://jsfiddle.net/bVkwH/8/

Danke im Voraus

46
Jagadeesh J

nun, ich glaube nicht, dass es einfach ist, dynamische @keyframes zu erstellen. Sie sind unflexibel, weil sie hart codiert sein müssen.

Übergänge sind etwas einfacher zu bearbeiten, da sie auf alle CSS-Änderungen, die von JavaScript ausgeführt werden, ordnungsgemäß reagieren können.

Die Komplexität, die CSS-Übergänge mit sich bringen können, ist jedoch ziemlich begrenzt - eine Animation mit mehreren Schritten ist schwer zu erreichen.

Dies ist ein Problem, das mit CSS @keyframe-Animationen gelöst werden soll , das jedoch nicht die dynamische Reaktionsfähigkeit bietet, die Übergänge bieten.

aber diese Links könnten Ihnen helfen

Link1 : Ein Tool, das eine @ -webkit-Keyframe-Animation mit vielen kleinen Schritten generiert. Dies öffnet die Tür zu einer unbegrenzten Auswahl an Lockerungsformeln.

Link2 Es wird eine große Hilfe für Sie sein, es als Basis zu nehmen, da es eine Benutzeroberfläche zum Erstellen von Animationen und Exporten bietet es zu CSS-Code.

Ich denke dies Lösung wird auf jeden Fall für Sie arbeiten. Es wird für dynamische Keyframes verwendet

32
Deep Sharma

Sie können Stylesheet-Regeln dynamisch einfügen, um vorherige Stile im Kopf zu überschreiben. Dies vermeidet das Hinzufügen einer weiteren Bibliothek für eine einzelne Aufgabe.

var style = document.createElement('style');
style.type = 'text/css';
var keyFrames = '\
@-webkit-keyframes spinIt {\
    100% {\
        -webkit-transform: rotate(A_DYNAMIC_VALUE);\
    }\
}\
@-moz-keyframes spinIt {\
    100% {\
        -webkit-transform: rotate(A_DYNAMIC_VALUE);\
    }\
}';
style.innerHTML = keyFrames.replace(/A_DYNAMIC_VALUE/g, "180deg");
document.getElementsByTagName('head')[0].appendChild(style);
44
Alex Grande

Die Antwort von Alex Grande ist für einige Keyframes großartig. Nehmen wir jedoch an, Sie möchten Keyframes immer und immer wieder dynamisch hinzufügen. Dann wird Ihre Webseite wirklich sehr schnell. Um dieses Problem zu lösen, BEENDEN Sie einfach das Erstellen neuer DOM-Elemente. Erstellen Sie stattdessen 1 neues DOM-Stylesheet und verwenden Sie es einfach wieder mit der inertRule. Wenn Sie noch mehr Keyframes benötigen (z. B. wenn Sie für jedes Animationsframe ein neues Keyframe generieren), müssen Sie ein System einrichten, das alte Keyframes löscht, wenn sie nicht mehr verwendet werden. Dies ist ein guter Anfang, wie man so etwas erreichen kann.

var myReuseableStylesheet = document.createElement('style'),
    addKeyFrames = null;
document.head.appendChild( myReuseableStylesheet );
if (CSS && CSS.supports && CSS.supports('animation: name')){
    // we can safely assume that the browser supports unprefixed version.
    addKeyFrames = function(name, frames){
        var pos = myReuseableStylesheet.length;
        myReuseableStylesheet.insertRule(
            "@keyframes " + name + "{" + frames + "}", pos);
    }
} else {
    addKeyFrames = function(name, frames){
        // Ugly and terrible, but users with this terrible of a browser
        // *cough* IE *cough* don't deserve a fast site
        var str = name + "{" + frames + "}",
            pos = myReuseableStylesheet.length;
        myReuseableStylesheet.insertRule("@-webkit-keyframes " + str, pos);
        myReuseableStylesheet.insertRule("@keyframes " + str, pos+1);
    }
}

Verwendungsbeispiel:

addKeyFrames(
    'fadeAnimation',
    '0%{opacity:0}' + 
    '100%{opacity:1}'
);

Auch Alex Grande, ich bin mir ziemlich sicher, dass document.getElementsByTagName('head')[0] und type = 'text/css' seit IE8 nicht mehr benötigt wurden und @keyframes erst ab IE10 unterstützt wird. Nur sagen ...

6
user7892745

Sie können den Stil in CSSKeyframeRule ändern. Dies funktioniert in Chrome gut, genau wie der folgende Code.

<html>

<head>
	<style>
		#text {
			display: inline-block;
		}
	</style>
</head>

<body>
	<div id="text">TEXT</div>
	<script>
	
		// Dynamically create a keyframe animation
		document.styleSheets[0].insertRule('\
			@keyframes anim {\
				from { transform: rotateZ(0deg);   }\
				to   { transform: rotateZ(360deg); }\
			}'
		);
		var div = document.getElementById('text');
		div.style.animation = 'anim 1s linear forwards';
		
		// This function will change the anim
		function stopAtSomeDeg(d) {
			var ss = document.styleSheets[0];
			var anim;
			for (var i in ss.cssRules) {
				// Find your animation by name
				if (ss.cssRules[i].name === 'anim') {
					anim = ss.cssRules[i];
					break;
				}
			}
			var stopFrame = anim.cssRules[1]; // This indicates the second line of "anim" above.
			
			// Change any attributes
			stopFrame.style.transform = 'rotateZ(' + d + 'deg)';
		}
		
		stopAtSomeDeg(180);
	</script>
</body>
</html>

1
WheatBerry

In JavaScript kann mit document.styleSheets auf das Stylesheet zugegriffen werden. Jedes Blatt hat eine Regel und/oder cssRule Liste (vom Browser abhängig) und eine CSSStyleSheet.insertRule () -Methode.

Mit dieser Methode können Sie ein neues keyframe raw als Zeichenfolge hinzufügen:

JavaScript

function insertStyleSheetRule(ruleText)
{
    let sheets = document.styleSheets;

    if(sheets.length == 0)
    {
        let style = document.createElement('style');
        style.appendChild(document.createTextNode(""));
        document.head.appendChild(style);
    }

    let sheet = sheets[sheets.length - 1];
    sheet.insertRule(ruleText, sheet.rules ? sheet.rules.length : sheet.cssRules.length);
}

document.addEventListener("DOMContentLoaded", event =>
{
    insertStyleSheetRule("@keyframes spinIt { 0% { transform: rotate(-20deg); } 100% { transform: rotate(20deg); } }");

    insertStyleSheetRule("#box { " + 
        "animation: spinIt 1s infinite alternate cubic-bezier(0.5,0,0.5,1); " + 
        "width: 64px; height: 64px; background-color: red; border: 4px solid black; " + 
    "}");
});

html

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

demo: https://jsfiddle.net/axd7nteu/

1
Martin Wantke

Sie können ein <style>-Element erstellen, den Inhalt auf das gewünschte CSS setzen, in diesem Fall die Deklaration Ihrer Animation, und es dem <head> der Seite hinzufügen.

Wie andere vorgeschlagen haben, sollten Sie, wenn Sie viele verschiedene Animationen erstellen müssen, einen einzelnen <style>-Tag wiederverwenden, anstatt mehrere davon zu erstellen und die neuen Stile mit CSSStyleSheet.insertRule() hinzuzufügen.

Wenn Sie schließlich template literals/strings von ES6 verwenden können, wird Ihr Code viel sauberer aussehen:

let dynamicStyles = null;

function addAnimation(body) {
  if (!dynamicStyles) {
    dynamicStyles = document.createElement('style');
    dynamicStyles.type = 'text/css';
    document.head.appendChild(dynamicStyles);
  }
  
  dynamicStyles.sheet.insertRule(body, dynamicStyles.length);
}

addAnimation(`
  @keyframes myAnimation { 
    0% { transform: rotate(0); }
    20% { transform: rotate(${ 360 * Math.random() }deg); }
    60% { transform: rotate(${ -360 * Math.random() }deg); }
    90% { transform: rotate(${ 360 * Math.random() }deg); }
    100% { transform: rotate(${ 0 }deg); }
  }
`);

document.getElementById("circle").style.animation = 'myAnimation 3s infinite';
html,
body {
  height: 100vh;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
}

#circle {
  width: 100px;
  height: 100px;
  box-shadow:
    0 0 48px -4px rgba(0, 0, 0, .25),
    0 0 0 4px rgba(0, 0, 0, .02);
  border-radius: 100%;
  position: relative;
  overflow: hidden;
}

#circle::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-2px);
  border-left: 4px solid #FFF;
  height: 24px;
  box-shadow: 0 -4px 12px rgba(0, 0, 0, .25);
}
<div id="circle"></div>

Oder noch besser:

let dynamicStyles = null;

function addAnimation(name, body) {
  if (!dynamicStyles) {
    dynamicStyles = document.createElement('style');
    dynamicStyles.type = 'text/css';
    document.head.appendChild(dynamicStyles);
  }
  
  dynamicStyles.sheet.insertRule(`@keyframes ${ name } {
    ${ body }
  }`, dynamicStyles.length);
}

addAnimation('myAnimation', `
  0% { transform: rotate(0); }
  20% { transform: rotate(${ 360 * Math.random() }deg); }
  60% { transform: rotate(${ -360 * Math.random() }deg); }
  90% { transform: rotate(${ 360 * Math.random() }deg); }
  100% { transform: rotate(${ 0 }deg); }
`);

document.getElementById("circle").style.animation = 'myAnimation 3s infinite';
html,
body {
  height: 100vh;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
}

#circle {
  width: 100px;
  height: 100px;
  box-shadow:
    0 0 48px -4px rgba(0, 0, 0, .25),
    0 0 0 4px rgba(0, 0, 0, .02);
  border-radius: 100%;
  position: relative;
  overflow: hidden;
}

#circle::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-2px);
  border-left: 4px solid #FFF;
  height: 24px;
  box-shadow: 0 -4px 12px rgba(0, 0, 0, .25);
}
<div id="circle"></div>

0
Danziger

Sie können ein neues Stylesheet mit der gewünschten Animation erstellen .. _. Beispiel:

function addAnimation(keyframe){
     var ss=document.createElement('style');
     ss.innerText=keyframe;
     document.head.appendChild(ss);
}

Dies würde ein neues Stylesheet mit Ihrer Animation erstellen.
Diese Methode wurde nur in Chrome getestet.

0

Lassen Sie mich eine aktualisierte (2019) Antwort auf diese Frage teilen. ** Ja, es ist ohne Javascript möglich ** mit CSS-Variablen (von allen modernen Browsern unterstützt).

--lightScaleStart: 0.8;

.light {
    animation: grow 2s alternate infinite ease-in-out;
}

.light.yellow {
    --lightScaleEnd: 1.1;
}

.light.red {
    --lightScaleEnd: 1.2;
}

@keyframes grow {
  from {
    transform: scale(var(--lightScaleStart));
  }
  to {
    transform: scale(var(--lightScaleEnd));
  }
}

Siehe Demo zu Codepen Dynamische CSS-Animationen mit CSS-Variablen

0
sandrina-p

der user7892745 funktioniert nicht für mich, ich brauche ein wenig anpassung

1 ° "pos" sollte nicht verstanden werden, aber das Konsolenprotokoll sagt "undefined" Also habe ich "pos" entfernt

2 ° "myReuseableStylesheet.insertRule" gibt mir einen Fehler "ist keine Funktion" Ich habe also "innerHTML" von "insertRule" verwendet.

3 ° Ich habe endlich " Document.head.appendChild (myReuseableStylesheet)" verschoben. Am Ende

aber danach funktioniert es gut und es ist genau das, wonach ich suche .... vielen dank user7892745: D

vielleicht ist das Problem, das ich hatte, so, wie ich es benutze

dies ist das Skript, das ich damit verwendet habe

var getclass = document.getElementsByClassName("cls");
var countclass = getclass.length;
for (var i=0; i <countclass; i++ ){
    getclass[i].addEventListener('mouseover', function(){
        // get the data-name value to show element whose id are the same
        var x=  this.getAttribute("data-name"); 
        var y =document.getElementById(x);
            y.style.display="block";
            // because the element to show have fixed width, but different text length, they have different height
            // so I need to get the highness, then use the value of height to define the 100% value of animation
            // or the longer ones will be cutted an the shorten have a lot of empty space a the end
        var yHeig= Math.round(parseInt(getComputedStyle(y).getPropertyValue('height')));
            yHeig_ = yHeig - 10; // to shorten a bit the time from end and new passage
        console.log(yHeig+" - "+ yHeig_);
        addKeyFrames(
                'showMe',
                '0%{top:35px;}' + 
                '100%{top:-'+ yHeig_ +'px;}'
            );
        y.style.animation="showMe 7s linear infinite";

    },false);

    getclass[i].addEventListener('mouseout', function(){
        var x=  this.getAttribute("data-name");
        document.getElementById(x).style.display="none";
    },false);
}

ich weiß, dass ein HTML Marquee Cuold sympathisch ist, um das gleiche zu tun, aber nicht gut funktionieren,

0
cippu_lux