有没有更好的方法可以对随机开始和结束的动画进行复杂的动画处理?

时间:2019-10-19 19:30:12

标签: javascript jquery html css animation

在此问题中,有一个可接受的答案How to create an animation with rarity of it to appear together with animations that always appear?

它包含了这个

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 个答案:

答案 0 :(得分:2)

我向您发布了解决方案,试图使整个动画非常易于创建和理解。

正如我在评论中说的那样,我的想法来自一个问题:“好吧,如果有时候有时候没有一些盒子,为什么我应该总是将它们全部放到舞台上?必须移动它“

因此,对于我的解决方案,所有框都是使用jquery动态创建的,循环了一个我称为“ ”的javascript对象:

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表示消失。有关此技术的更多信息,请参见此:Fade out, pause, then fade in an element - CSS Only。您必须使用一个比例来找到确切的百分比(在我的示例中为14%和86%)。

最后一个arg只是框的背景颜色。

为了计算在舞台上出现的可能性,我使用了一个随机数和在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>