Есть ли лучший способ делать сложные анимации с рандомизированной анимацией начала и конца? - PullRequest
0 голосов
/ 19 октября 2019

На этот вопрос есть принятый ответ Как создать анимацию с редкостью, чтобы она появлялась вместе с постоянно появляющимися анимациями?

Содержит это

https://jsfiddle.net/d25kx6cj/5/

<div id="boxes">
  <div id="box1" class="box"></div>
  <div id="box2" class="box"></div>
  <div id="box4" class="box"></div>
  <div id="box3" class="box"></div>
</div>

Но, похоже, это слишком сложно. Есть ли другой способ.

Дело в том, что все может стать сложнее.

Я пытаюсь добиться этого более простым способом:

var box1 = document.getElementById("box1"); /* The one with the rarity */

var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3"); /* Maybe give it a chance of which color */

var boxes = document.getElementById("boxes");

var box3Colors = {"blue": 90, "red": 50};

var btn = document.getElementById("btn");
btn.addEventListener("click", toggleAnimation);

boxes.classList.add("deactivated");

function randomizerWithChances(input) {
    var array = [];
    for(var item in input) {
        if ( input.hasOwnProperty(item) ) {
            for( var i=0; i<input[item]; i++ ) {
                array.push(item);
            }
        }
    }
    /*console.log(array)
    var randomizerValue = Math.floor(Math.random() * array.length);
    console.log(randomizerValue)*/
    return array[Math.floor(Math.random() * array.length)];
}

function propertyFromStylesheet(selector, attribute) {
    var value;

    [].some.call(document.styleSheets, function (sheet) {
        return [].some.call(sheet.rules, function (rule) {
            if (selector === rule.selectorText) {
                return [].some.call(rule.style, function (style) {
                    if (attribute === style) {
                        value = rule.style.getPropertyValue(attribute);
                        return true;
                    }

                    return false;
                });
            }

            return false;
        });
    });

    return value;
}

var box1_defaultDurs = propertyFromStylesheet("#box1", "animation-duration");
var box2_defaultDur = parseFloat(propertyFromStylesheet("#box2", "animation-duration"));
var box4_defaultDur = parseFloat(propertyFromStylesheet("#box4", "animation-duration"));
var box3_defaultDurs = propertyFromStylesheet("#box3", "animation-duration");

var box1AppearChance = {no:6, yes:4} /* 40% Appear chance I guess*/
var box4AppearChance = {no:8, yes:2}

/*
defaultDurs.split(",").map(function(item) {
  return item.trim();
});*/

var box1_defaultDur = box1_defaultDurs.split(",").map(function(item) {
  return item.trim();
});
var box3_defaultDur = box3_defaultDurs.split(",").map(function(item) {
  return item.trim();
});


var box1_defaultDurStart = parseFloat(box1_defaultDur[0]);
var box1_defaultDurEnd = parseFloat(box1_defaultDur[1]);

var box3_defaultDurStart = parseFloat(box3_defaultDur[0]);
var box3_defaultDurEnd = parseFloat(box3_defaultDur[1]);

var box3_delays = [];


function animationHandler() {
  box3.style.backgroundColor = randomizerWithChances(box3Colors);
  
  var box1Value = randomizerWithChances(box1AppearChance);
  var box4Value = randomizerWithChances(box4AppearChance);
  /*console.log(box1Value)*/
  
  box3_delays[0] = "0s"; /* Put first delay value */
  
  if (box1Value == "yes") {
  	box1.classList.add("active");
    
    box2.style.animationDelay = box1_defaultDurStart + "s";
    box3_delays[0] = box1_defaultDurStart + "s";
 }
 
 if (box1Value == "yes" || box4Value == "yes") {
  	box3_delays[0] = parseFloat(box3_delays[0]) + box2_defaultDur + "s";
  }
  
    /*box3.style.animationDelay = box3_defaultDurs.split(",").map(function(item) {
    	var itemTrimmed = item.trim();

    	return parseFloat(itemTrimmed) + box1_defaultDurStart + box2_defaultDur + "s";
    });
  }*/
  /* Use this incase you have to summarize something with two delays, if it has 0s you might want to do something else or check if it's the first one in the array just to leave it alone. But in this case I didn't needed it */
  
 
 /* box4.style.animationDelay = "0s"; To prevent NaN 
 Don't do this it it just breaks it just check it
 */
  
  if (box4Value == "yes") {
  	box4.classList.add("active");
    
    if ( isNaN(parseFloat(box2.style.animationDelay)) ) {
    	box4.style.animationDelay = box2_defaultDur + "s";
    }
    else if ( !isNaN(parseFloat(box2.style.animationDelay)) ) {
      box4.style.animationDelay = parseFloat(box2.style.animationDelay) + box2_defaultDur + "s";
    } /* box4 doesn't have a delay and we set one */
    
  	box3_delays[0] = parseFloat(box3_delays[0]) + box4_defaultDur + "s";
    /* Delay of box3 is getting extended because of box4 when it appears */
	}


  if (box1Value == "yes" || box4Value == "yes") {
  	box3.style.animationDelay = [ parseFloat(box3_delays[0]) + "s", parseFloat(box3_delays[0]) + parseFloat(box3_defaultDurStart) + "s" ];
  }
  
 if (box1Value == "yes") {
  	if (box4Value == "no") {
      box1.style.animationDelay = ["0s", box2_defaultDur + box3_defaultDurStart + box1_defaultDurStart + box3_defaultDurEnd + "s"]
    }
   	else {
    	box1.style.animationDelay = ["0s", box2_defaultDur + box3_defaultDurStart + parseFloat(box4.style.animationDelay) + box1_defaultDurStart + box3_defaultDurEnd + "s"];
    }
    /* The + 2 is because of the box1_defaultDurStart which is needed */
    /* And box3_defaultDurEnd also needed in this case */
	}
}

function animationHandlerReset() { 
	box1.classList.remove("active");
  box4.classList.remove("active"); /* And don't forget to remove the class at the end*/
  
  /* Reset to default to stylesheet */
  box1.style.removeProperty("animation-delay");
  box2.style.removeProperty("animation-delay");
  box3.removeAttribute("style"); /* or you could do this if you didn't give it any inline style by default */
  box4.style.removeProperty("animation-delay");
} 


function toggleAnimation() {
	if (!boxes.classList.contains("deactivated")) {
  	animationHandlerReset();
		boxes.classList.add("deactivated");
    btn.innerHTML = "Start Animation";
  }
 	else if (boxes.classList.contains("deactivated")) {
  	animationHandler();
  	boxes.classList.remove("deactivated");
    btn.innerHTML = "Stop Animation"
  }
}
#boxes {
  
}

.active {
  display: inline-block!important;
}

.deactivated {
  display: none!important;
  /*visibility: hidden!important;*/
}

.box {
  display: inline-block;
  position: relative;
  height: 50px;
  width: 50px;
  margin-left: 20px;
}

#box1 {background: #00afe8;}
#box2 {background: green;}
#box3 {background: blue;}
#box4 {background: orange;}

@keyframes box1-up {
  0% { top: 70px;}
  100% {top: 0px;}
}

@keyframes box1-down {
  0% { top: 0px;}
  100% {top: 70px; opacity: 0;}
}

@keyframes box4-anim {
  0% { height: 50px; width: 50px; transform: scale(0.5) rotate(0deg); }
  100% { height: 50px; width: 50px; transform: scale(1) rotate(180deg); }
}

@keyframes blend {
  0% { opacity: 0; }
  100% { opacity: 1; }
}


#box1 {
  top: 70px;
  display: none;
  animation: box1-up 2s, box1-down 3s;
  animation-fill-mode: forwards;
}


#box2 {
  opacity: 0;
  animation: blend 3s;
  animation-fill-mode: forwards;
  /*animation-delay: 3s;*/
}

#box3 {
  opacity: 0;
  animation: blend 3s, blend 4s reverse;
  animation-fill-mode: forwards;
  animation-delay: 3s, 6s; /* Both delays start together. Probably you want the other delay to be the twice as the size of the first one in this case for the end, but maybe not everytime */
}

#box4 {
  display: none;
  height: 0px;
  width: 0px;
  animation: box4-anim 1s;
  animation-fill-mode: forwards;
}
<div id="boxes">
  <div id="box1" class="box"></div>
  <div id="box2" class="box"></div>
  <div id="box4" class="box"></div>
  <div id="box3" class="box"></div>
</div>


<button id="btn" style="margin-top: 200px;">Start Animation</button> 

Упрощенная версия этого?

В основном это анимация, но есть случайный шанс, чтоодин из них появляется. Таким образом, у box1 есть случайный шанс, что он появляется, и box4, который является оранжевым, просто был назван так. Имеет случайный шанс появиться. И box1, и box3 имеют начальную и конечную анимацию. И это все, что нужно рассчитать, а затем использовать, и мне было интересно, есть ли более простой способ сделать это, потому что это так много, и я не уверен.

Я думаю, что jQuery, но я не знаю ничего хорошегопример этому.

1 Ответ

2 голосов
/ 20 октября 2019

Я отправляю вам свое решение, пытаясь сделать всю анимацию очень простой для создания и понимания.

Как я уже говорил в моих комментариях, моя идея возникла из вопроса: " Хорошо, если некоторыеящиков иногда нет, почему я должен всегда ставить их все на сцену? Я ставлю на сцену, только если мне нужно переместить ее"

Итак, для моего решения все коробки созданы наfly with jquery, зацикливающий объект javascript, который я называю " boxes ":

var boxes={
    "box1":{
        percentual:         40,             // 40% to appear on stage
        animation:          "box-up-down",  // animation name
        backgroundColor:    "green"         // background color
    },
    "box2":{
        percentual:         100, 
        animation:          "fade-in",
        backgroundColor:    "orange"
    },
    "box3":{
        percentual:         100,
        animation:          "fade-in",
        backgroundColor:    "blue"
    },
    "box4":{
        percentual:         20,
        animation:          "fade-in-out",
        backgroundColor:    "pink"
    },
    "box5":{
        percentual:         100,
        animation:          "rotate-in-out",
        backgroundColor:    "red"
    }
}

В этом объекте вы можете указать, сколько ящиков вы хотите (в моем примере их 5). Первое значение - вероятность появления на сцене (40% - первое, 100% - второе ...). Второй определяет название анимации, которую я написал в CSS:

/*ANIMATIONS*/

.fade-in {
    animation: fade-in 1s ease forwards;
}

.fade-in-out {
    animation: fade-in-out 7s ease forwards;
}

.box-up-down {
    animation: box-up-down 7s ease forwards;
}

.rotate-in-out {
    animation: rotate-in-out 7s ease forwards;
}


@keyframes fade-in {
    0% {
        opacity: 0;
    }
    100% {
        opacity: 1;
    }
}

@keyframes fade-in-out {
    0% {
        opacity: 0;
    }
    14% {
        opacity: 1;
    }
    86% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}

@keyframes box-up-down {
    0% {
        top: 70px; 
        opacity: 0;
    }
    14% {
        top: 0; 
        opacity: 1;
    }
    86% {
        top: 0; 
        opacity: 1;
    }
    100% {
        top: 70px; 
        opacity: 0;
    }
}

@keyframes rotate-in-out {
    0% {
        transform: scale(0.5) rotate(0deg);
        opacity: 0;
    }
    14% {
        transform: scale(1) rotate(180deg);
        opacity: 1;
    }
    86% {
        transform: scale(1) rotate(180deg);
        opacity: 1;
    }
    100% {
        transform: scale(0.5) rotate(0deg);
        opacity: 0;
    }
}

Важно понимать, что в самой анимации установлена ​​пауза. В моем примере я использовал 7 секунд анимации: 1 для появления, 5 для периода паузы и 1 для исчезновения. См. Это для получения дополнительной информации о технике: Исчезновение, пауза, затем исчезновение в элементе - CSS Only . Вы должны использовать пропорцию, чтобы найти точное процентное значение (в моем примере это было 14% и 86%).

Последний аргумент - это только цвет фона поля.

Для вычислениявероятность появления на сцене, я использовал простое сравнение между случайным числом и моим процентом, установленным в объекте javascript:

let random=Math.floor(Math.random() * 100) + 1; //random number from 1 to 100

if(value.percentual>=random){
 //create my box
}

Это все сценарий в действии:

var boxes = {
    "box1": {
        percentual: 40, // 40% to appear on stage
        animation: "box-up-down", // animation name
        backgroundColor: "green" // background color
    },
    "box2": {
        percentual: 100,
        animation: "fade-in",
        backgroundColor: "orange"
    },
    "box3": {
        percentual: 100,
        animation: "fade-in",
        backgroundColor: "blue"
    },
    "box4": {
        percentual: 20,
        animation: "fade-in-out",
        backgroundColor: "pink"
    },
    "box5": {
        percentual: 100,
        animation: "rotate-in-out",
        backgroundColor: "red"
    }
}


$("#btn").on("click", function(e) {

    // set the init situation if I double click during the animations
    let i = 0;
    $("#boxes").html("");


    // Create every block
    $.each(boxes, function(index, value) {

        let random = Math.floor(Math.random() * 100) + 1; //random number from 1 to 100

        if (value.percentual >= random) {

            let myBox = `<div id="${index}"
								class="box ${value.animation}"
								style="background-color:${value.backgroundColor};
									   animation-delay:${i}s;"
								></div>`;

            $(myBox).appendTo("#boxes");

            i++;
        }
    });
});
.box {
	  display: inline-block;
	  position: relative;
	  transition: all 1s;
	  height: 50px;
	  width: 50px;
	  opacity:0;
	  background-color:#f2f2f2;
	  margin-right: 20px;
	}

	/*ANIMATIONS*/

	.fade-in {
		animation: fade-in 1s ease forwards;
	}

	.fade-in-out {
		animation: fade-in-out 7s ease forwards;
	}

	.box-up-down {
		animation: box-up-down 7s ease forwards;
	}

	.rotate-in-out {
		animation: rotate-in-out 7s ease forwards;
	}


	@keyframes fade-in {
		0% {
    		opacity: 0;
	    }
	    100% {
	    	opacity: 1;
	    }
	}

	@keyframes fade-in-out {
	    0% {
    		opacity: 0;
	    }
	    14% {
	    	opacity: 1;
	    }
	    86% {
	        opacity: 1;
	    }
	    100% {
	        opacity: 0;
	    }
	}

	@keyframes box-up-down {
	  	0% {
    		top: 70px; 
    		opacity: 0;
	    }
	    14% {
	    	top: 0; 
	    	opacity: 1;
	    }
	    86% {
	        top: 0; 
	        opacity: 1;
	    }
	    100% {
	        top: 70px; 
	        opacity: 0;
	    }
	}

	@keyframes rotate-in-out {
		0% {
    		transform: scale(0.5) rotate(0deg);
    		opacity: 0;
	    }
	    14% {
	    	transform: scale(1) rotate(180deg);
	    	opacity: 1;
	    }
	    86% {
	        transform: scale(1) rotate(180deg);
	        opacity: 1;
	    }
	    100% {
	        transform: scale(0.5) rotate(0deg);
    		opacity: 0;
	    }
	}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="boxes"></div>

<button id="btn" style="margin-top: 200px;">Start Animation</button>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...