使用不同的关键帧值为新创建的对象设置动画

时间:2017-09-05 11:53:51

标签: javascript css animation

所以我正在尝试制作简单的动画。当你按下蓝色容器内的某个地方时,应该在这个地方创建一个圆圈然后上升。经过一些研究后,我发现了如何将JS值放入关键帧中,但它改变了每个对象的值,而不仅仅是新创建的。如果你运行剪切并按下某处高处然后某处低,你会看到我在说什么。

我找到了一些带有Raphael库的AWESOME解决方案,但我是初学者,我正试图在JS中制作这样的东西。它甚至可能吗?怎么样?

var bubble = {
    posX: 0,
    posY: 0,
    size: 0
  };

var aquarium = document.getElementById("container");

var ss = document.styleSheets;
var keyframesRule = [];
function findAnimation(animName) { //function to find keyframes and insert replace values in them
  for (var i = 0; i < ss.length; i++) {
    for (var j = 0; j < ss[i].cssRules.length; j++) {
      if (window.CSSRule.KEYFRAMES_RULE == ss[i].cssRules[j].type && ss[i].cssRules[j].name == animName) {
        keyframesRule.push(ss[i].cssRules[j]);
      }
    }
  }
  return keyframesRule;
}


function changeAnimation (nameAnim) {  //changing top value to cursor position when clicked
  var keyframesArr = findAnimation(nameAnim);
  for (var i = 0; i < keyframesArr.length; i++) {
    keyframesArr[i].deleteRule("0%");
    keyframesArr[i].appendRule("0% {top: " + bubble.posY + "px}");
  }
}


function createBubble(e) {
  "use strict";
  bubble.posX = e.clientX;
  bubble.posY = e.clientY;
  bubble.size = Math.round(Math.random() * 100);
  var bubbleCircle = document.createElement("div");
  aquarium.appendChild(bubbleCircle);
  bubbleCircle.className = "bubble";
  var bubbleStyle = bubbleCircle.style;
  bubbleStyle.width = bubble.size + "px";
  bubbleStyle.height = bubble.size + "px";
  bubbleStyle.borderRadius = (bubble.size / 2) + "px";
  //bubbleStyle.top = bubble.posY - (bubble.size / 2) + "px";
  bubbleStyle.left = bubble.posX - (bubble.size / 2) + "px";
  changeAnimation("moveUp");
  bubbleCircle.className += " animate";
}

aquarium.addEventListener("click", createBubble);
//console.log(bubble);
body {
  background-color: red;
  margin: 0;
  padding: 0;
}

#container {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 80px;
  left: 0;
  background-color: rgb(20,255,200);
}

#surface {
  width: 100%;
  height: 40px;
  position: fixed;
  top: 40px;
  opacity: 0.5;
  background-color: rgb(250,250,250);
}

.bubble {
  position: fixed;
  border: 1px solid blue;
}

.animate {
  animation: moveUp 5s linear;//cubic-bezier(1, 0, 1, 1);
  -webkit-animation: moveUp 5s linear;//cubic-bezier(1, 0, 1, 1);
}


@keyframes moveUp{
  0% {
    top: 400px;
  }
  100% {
    top: 80px;
  }
}

@-webkit-keyframes moveUp{
  0% {
    top: 400px;
  }
  100% {
    top: 80px;
  }
}
<body>
  <div id="container">
  </div>
  <div id="surface">
    
  </div>
</body>

2 个答案:

答案 0 :(得分:2)

这是一个可能的解决方案。我做了什么:

  • 删除您的功能changeAnimation ()findAnimation() - 我们不需要它们
  • 更新关键帧看起来像 - 只关注 100%

    @keyframes moveUp { 100% {top: 80px;} }

  • 使用top

  • 分配新气泡的clientY
  • 5秒钟后,将气泡的top设置为#container 80px )的偏移量 - 正好在动画结束时保持气泡的位置泡沫,否则它将返回初始位置

&#13;
&#13;
var bubble = {
  posX: 0,
  posY: 0,
  size: 0
};

var aquarium = document.getElementById("container");

function createBubble(e) {
  "use strict";
  bubble.posX = e.clientX;
  bubble.posY = e.clientY;

  bubble.size = Math.round(Math.random() * 100);
  var bubbleCircle = document.createElement("div");
  aquarium.appendChild(bubbleCircle);
  bubbleCircle.className = "bubble";
  var bubbleStyle = bubbleCircle.style;
  bubbleStyle.width = bubble.size + "px";
  bubbleStyle.height = bubble.size + "px";
  bubbleStyle.borderRadius = (bubble.size / 2) + "px";
  bubbleStyle.top = bubble.posY - (bubble.size / 2) + "px";
  bubbleStyle.left = bubble.posX - (bubble.size / 2) + "px";
  bubbleCircle.className += " animate";

  // The following code will take care to reset top to the top 
  // offset of #container which is 80px, otherwise circle will return to 
  // the position of which it was created
  (function(style) {
    setTimeout(function() {
      style.top = '80px';
    }, 5000);
  })(bubbleStyle);
}

aquarium.addEventListener("click", createBubble);
&#13;
body {
  background-color: red;
  margin: 0;
  padding: 0;
}

#container {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 80px;
  left: 0;
  background-color: rgb(20, 255, 200);
}

#surface {
  width: 100%;
  height: 40px;
  position: fixed;
  top: 40px;
  opacity: 0.5;
  background-color: rgb(250, 250, 250);
}

.bubble {
  position: fixed;
  border: 1px solid blue;
}

.animate {
  animation: moveUp 5s linear;
  /*cubic-bezier(1, 0, 1, 1);*/
  -webkit-animation: moveUp 5s linear;
  /*cubic-bezier(1, 0, 1, 1);*/
}

@keyframes moveUp {
  100% {
    top: 80px;
  }
}

@-webkit-keyframes moveUp {
  100% {
    top: 80px;
  }
}
&#13;
<body>
  <div id="container"></div>
  <div id="surface"></div>
</body>
&#13;
&#13;
&#13;

您的代码存在的问题是它全局更改了 @keyframes moveUp ,导致所有气泡移动。

答案 1 :(得分:2)

您的代码存在的问题是您正在更新应用于所有气泡的关键帧。我尝试了另一种方法,使用transition并在元素添加到DOM后更改top位置(否则它不会被动画化)。

这里的主要问题是等待元素添加到DOM。我尝试使用MutationObserver但似乎在元素实际添加到DOM(或至少渲染)之前调用它。所以我找到的唯一方法是使用超时来模拟这种等待,虽然必须有一个更好的(因为它可能被称为太早,导致气泡直接粘到顶部),我很乐意听到约。

var bubble = {
  posX: 0,
  posY: 0,
  size: 0
};

var aquarium = document.getElementById("container");

function createBubble(e) {
  "use strict";
  bubble.posX = e.clientX;
  bubble.posY = e.clientY;
  bubble.size = Math.round(Math.random() * 100);

  var bubbleCircle = document.createElement("div");
  aquarium.appendChild(bubbleCircle);

  bubbleCircle.classList.add("bubble");
  var bubbleStyle = bubbleCircle.style;

  bubbleStyle.width = bubble.size + "px";
  bubbleStyle.height = bubble.size + "px";
  bubbleStyle.borderRadius = (bubble.size / 2) + "px";
  bubbleStyle.top = bubble.posY - (bubble.size / 2) + "px";
  bubbleStyle.left = bubble.posX - (bubble.size / 2) + "px";

  setTimeout(function() {
    bubbleCircle.classList.add("moveUp");
  }, 50);
}

aquarium.addEventListener("click", createBubble);
body {
  background-color: red;
  margin: 0;
  padding: 0;
}

#container {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 80px;
  left: 0;
  background-color: rgb(20, 255, 200);
}

#surface {
  width: 100%;
  height: 40px;
  position: fixed;
  top: 40px;
  opacity: 0.5;
  background-color: rgb(250, 250, 250);
}

.bubble {
  position: fixed;
  border: 1px solid blue;
  transition: 5s;
}

.moveUp {
  top: 80px !important;
}
<body>
  <div id="container">
  </div>
  <div id="surface">

  </div>
</body>

另外,我使用了classList对象而不是className += ...,因为它更可靠。