Подтвердить что ты не робот

Как динамически создавать анимации CSS "@-Keyframe"?

У меня есть требование вращать div и останавливаться на определенной позиции (значение будет получено с сервера).

Я пытался вращать и останавливать нативный JS, но он сильно загружает мой процессор.

Я могу вращаться с помощью CSS-анимации, но мне нужно создать класс, который будет динамически описывать, где останавливать анимацию. Что-то вроде

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

Вот одна ссылка

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

Заранее спасибо

4b9b3361

Ответ 1

ну, я не думаю, что легко создавать динамические @keyframes они негибкие, потому что они должны быть жестко закодированы.

С переходами работать немного проще, поскольку они могут корректно реагировать на любые изменения CSS, выполняемые JavaScript.

Однако сложность, которую могут дать CSS-переходы, довольно ограничена - сложно выполнить анимацию с несколькими шагами.

Это проблема, которую должны решить CSS @keyframe-анимации, но они не обеспечивают такой уровень динамической отзывчивости, как у переходов.

но эти ссылки могут помочь вам

Link1: инструмент, который генерирует анимацию @-webkit-keyframe с множеством маленьких шагов. Это открывает путь к неограниченному выбору формулы смягчения.

Link2 Это может быть очень полезно.

Link3 поможет вам взять его за основу, поскольку он предоставляет пользовательский интерфейс для создания анимации и экспорта в код CSS.

Я думаю, что это решение определенно будет работать для вас. Его используют для динамических ключевых кадров

Ответ 2

Вы можете вставлять правила стилей динамически, чтобы переопределить предыдущие стили в голове. Это помогает избежать добавления еще одной библиотеки для одной задачи.

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);

Ответ 3

Алекс Гранде ответ работает отлично для нескольких ключевых кадров. Но, скажем, вы хотите динамически продолжать добавлять ключевые кадры снова и снова, тогда ваша веб-страница становится очень медленной и очень быстрой. Чтобы решить эту проблему, просто прекратите создавать новые элементы DOM. Вместо этого создайте 1 новую таблицу стилей DOM и просто используйте ее с помощью inertRule. Если вам нужно еще больше ключевых кадров (например, если вы генерируете новый ключевой кадр каждый анимационный кадр), то вам нужно настроить систему, которая удаляет старые ключевые кадры после того, как они больше не используются. Это хорошее начало того, как чего-то подобного можно достичь.

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);
    }
}

Пример использования:

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

Кроме того, Алекс Гранде, я почти уверен, что document.getElementsByTagName('head')[0] и type = 'text/css' не нужны с IE8, и @keyframes не поддерживаются до IE10. Просто говорю...

Ответ 4

Вы можете изменить стиль в CSSKeyframeRule, и это прекрасно работает для меня в Chrome, так же, как и код ниже. Надеюсь, это поможет :)

<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>

Ответ 5

В JavaScript возможно получить доступ к таблице стилей с помощью document.styleSheets. Каждый лист имеет правило и/или список cssRule (зависит от браузера) и метод CSSStyleSheet.insertRule().

Этот метод позволяет добавить новый ключевой кадр raw в виде строки:

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>

демо: https://jsfiddle.net/axd7nteu/

Ответ 6

user7892745 не будет работать для меня, нужна небольшая корректировка

1 ° "pos" не понимает, что wot должен быть, но в консольном журнале говорится "undefined" поэтому я удаляю ", pos"

2 ° "myReuseableStylesheet.insertRule" дать мне ошибку "не является функцией" поэтому я использовал "innerHTML" insted из "insertRule"

3 ° Наконец я переехал "document.head.appendChild(myReuseableStylesheet);" в конце

но после этого он отлично работает, и он точно то, что я ищу. Большое спасибо пользователю7892745: D

может быть, проблема у меня возникла, как я ее использую

это script i, который использовался с ним

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);
}

Я знаю, что html marquee cuold кажется симпатичным, чтобы делать то же самое, но не работает хорошо,

Ответ 7

Вы можете создать элемент <style>, установить его содержимое на нужный вам CSS, в данном случае, объявление вашей анимации и добавить его в <head> страницы.

Кроме того, как предлагали другие, если вам нужно создать много разных анимаций, было бы лучше повторно использовать один <style> а не создавать их несколько, и добавлять новые стили с помощью CSSStyleSheet.insertRule().

Наконец, если вы можете использовать литералы/строки шаблона ES6, ваш код будет выглядеть намного чище:

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>

Ответ 8

Вы можете создать новую таблицу стилей с нужной вам анимацией. Например:

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

Это создаст новую таблицу стилей с вашей анимацией.
Этот метод был протестирован только в Chrome.

Ответ 9

Позвольте мне поделиться обновленным (2019) ответом на этот вопрос. ** Да, это возможно без Javascript ** с использованием CSS-переменных (поддерживается всеми современными браузерами).

--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));
  }
}

Смотрите демонстрацию по динамической CSS-анимации Codepen с помощью CSS-переменных.