Как создать анимацию с редкостью, чтобы она появлялась вместе с анимациями, которые появляются всегда? - PullRequest
2 голосов
/ 18 октября 2019

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

Пример здесь:

enter image description here

Число 1 имеет редкий шанс появиться, скажем, 40%. Когда он не появляется, он начинается с 2 , а затем после анимации 2 3 начинается.

Если это 1 используйте шанс, он появится и начнет двигаться вверх, и после завершения анимации будет воспроизводиться 2 , а затем через 2 - 3 . Таким образом, они просто смешиваются в качестве примера.

2 и 3 всегда будут появляться, но у 1 есть 40% для его появления,как пример. На 3 мне удалось добавить случайный фоновый шанс. Я прокомментировал этот код.

Если 1 не появится, то он должен действовать как display: none. Однако, когда я ставлю display: none на box1, анимация никогда не запускается или не запускается, но я ее не вижу, но помещаю в ключевые кадры.

Что яЯ думаю, мне нужен Javascript, чтобы он мог изменить свойство CSS animation-delay, хотя я не уверен.

Это то, что у меня есть: https://jsfiddle.net/edy3xjvz/2/

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}; /* Blue has 90% chance and red has 50% not sure if done right, but what if I want to add a "green" with the chance of 90% too like "blue"???  */


/* Probably has to be done here, or when reaching a certain area, maybe with a button */
/*document.onload*/

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

boxes.style.display = "none";

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);
            }
        }
    }
    return array[Math.floor(Math.random() * array.length)];
}


/* Start Animation */
function startAnimation() {
	boxes.style.display = "none"; /* to replay but doesn't work*/
  
	/* Do radomize stuff */
  /* Don't really know for box1 */
  
 
  /* I've tried box3, like that before
  var random2 = box3Colors[Math.floor(Math.random() * box3Colors.length)]
  box3.style.backgroundColor = random2;*/
  box3.style.backgroundColor = randomizerWithChances(box3Colors);

	/* Animation starts here */
	boxes.style.display = "block";
}
#boxes {
  
}

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

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

@keyframes box1-up {
  0% { top: 70px; position: relative; visibility: visible;}
  100% {top: 0px; position: relative; visibility: visible;}
}

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


#box1 {
  top: 70px;
  /* display: none; Can't start with this I wanted that when it isn't there, it should not appear but with display: none it didn't work because it can never appear then */
  /*position: absolute; visibility: hidden;*/ /* So had to use this but when using this
                                             it didn't work the box is somehow upside 
                                             https://i.imgur.com/3vER5ja.png so not sure */
  animation: box1-up 2s;
  animation-fill-mode: forwards;
}


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

#box3 {
  opacity: 0;
  animation: blend 3s;
  animation-fill-mode: forwards;
  animation-delay: 5s;
}
<div id="boxes">
  <div id="box1" class="box"></div>
  <div id="box2" class="box"></div>
  <div id="box3" class="box"></div>
</div>


<button id="btn" style="margin-top: 200px;">Start Animation</button> 
Ниже должна быть кнопка. Я попробовал поставить рандомизатор для box3 цвета фона, похоже, работает. Я пытался использовать box1 , но display: none сломал его.

Я пытался сделать что-то, что, когда анимация вообще не запускается, этот box2 как будто не здесь, но когда я использую display: none анимация никогда не запускается, не знаю почему. https://jsfiddle.net/edy3xjvz/3/

Затем я удалил его, так что это то, что вы видели на фрагменте выше. https://jsfiddle.net/edy3xjvz/4/

Ответы [ 2 ]

1 голос
/ 19 октября 2019

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

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

Это первая концепция:

https://jsfiddle.net/8z9obyLh/

Также вы должны заметить, что после того, как дисплей исчезнет, ​​отсрочка начнется оттуда, в зависимости от того, какой элемент только что вышел из дисплея.

Другой имеет немного сложный способ, но просто посмотрите наэто и как это делается.

Tbh, должен быть другой способ сделать это, который, я думаю, есть.

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

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> 
1 голос
/ 18 октября 2019

Вот краткий обзор того, как он может вести себя с нашим без box1, если я правильно понимаю ваше описание, так что, если есть класс active, он будет выглядеть так, как у вас, а если нет, тогда даст иллюзионный эквивалентdisplay: none, надеюсь, это поможет, ура.

const box1 = document.getElementById('box1');

toggleActive = () => {
  let classes = box1.classList;
  classes.contains('active') ? classes.remove('active') : classes.add('active');
}
.container {
  display: inline-block;
  outline: lightgray 1px dashed;
  padding: 1rem;
  margin: 1rem;
}

.container div {
  display: inline-block;
  height: 5rem;
  width: 5rem;
  background-color: lime;
  opacity: 0;
  animation: reveal 3s ease forwards;
}

.container div:nth-child(2) {
  animation-delay: 1s;
}

.container div:nth-child(3) {
  animation-delay: 2s;
}

.container div:not(:last-child) {
  margin-right: 1rem;
}

#box1 {
  height: 0;
  width: 0;
  margin: 0;
  transform: translateY(6rem);
  transition: transform 1s ease;
}

#box1.active {
  height: 5rem;
  width: 5rem;
  margin-right: 1rem;
  animation: revealUp 2s ease forwards;
}

@keyframes reveal {
  to { opacity: 1 }
}

@keyframes revealUp {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
<div class="container">
  <div id="box1" class="active"></div>
  <div id="box2"></div>
  <div id="box3"></div>
</div>

<br/>

<button onclick="toggleActive()">Toggle First One</button>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...