在 Javascript/CSS 中实现图标变形动画?

Implement Icon morph animation in Javascript/CSS?

观看此视频

(高清视频here)

我想知道在 Javascript/CSS 中是否有更简单的方法来实现它。

我知道有一些 CSS3 属性,例如 transitionanimationtransform 等等,但据我所知,none 这些属性可以将一个图标转换为另一个图标,并提供像上面视频中的左上角和右上角的精致效果

有没有人知道什么是实施这个的好的解决方案?

您可以随时尝试一些 css 过滤器与一些过渡相结合 不需要 javascript。但是你可以使用 javascript 附加和删除 类 这样你就可以在不同的情况下有不同的动画。

.showbox {
    float: left;
    margin: 4em 1em;
    width: 100px;
    height: 60px;
    border: 2px solid green;
    background-color: #fff;
    line-height: 60px;
    text-align: center;
    
    -webkit-transition: 1s ease-in-out;
    -moz-transition: 1s ease-in-out;
    -o-transition: 1s ease-in-out;
    transition: 1s ease-in-out;
  }
  .showbox.slideright:hover {
    -webkit-transform: translate(3em,0) rotate(360deg);
    -moz-transform: translate(3em,0) rotate(360deg);
    -o-transform: translate(3em,0) rotate(360deg);
    -ms-transform: translate(3em,0) rotate(360deg);
    transform: translate(3em,0) rotate(360deg);
  }
<div class="showbox slideright">box 1</div>

您的设计在 css 下完全可行。所有这些都需要略有不同的方法(如您在我的演示中所见),但都是完全可能的。

例如,

  • 左上部分可以用两个伪元素制作,并在悬停时旋转和更改边框。
  • 可以使用 border-hack 创建右上角,在悬停时更改边框和宽度
  • 左下方可以创建如图
  • 可以使用多个伪元素和 data-attr 中的更改来创建右下角。 (例如,如果您随后想要 +3,则必须通过 javascript 更改 data-start 属性)

img {
  height: 200px;
  width: 200px;
}
div {
  height: 200px;
  width: 200px;
  position: relative;
  display: inline-block;
}
.one {
  background: lightgreen;
}
*:before,
*:after,
a {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transition: all 0.6s;
}
.one:before {
  height: 40px;
  width: 60px;
  border: 10px solid white;
  border-left: 0px solid white;
  border-right: 0px solid white;
}
.one:after {
  height: 10px;
  width: 60px;
  background: white;
}
.one:hover:before {
  transform: translate(-50%, -50%) rotate(135deg);
  border-bottom: 10px solid white;
  border-right: 10px solid white;
  border-top: 0px solid white;
  width: 40px;
}
.one:hover:after {
  transform: translate(-50%, -50%) rotate(180deg);
}
.two {
  background: orange;
}
.three {
  background: steelblue;
}
.four {
  background: tomato;
}
.two:before {
  width: 0;
  border-left: 50px solid white;
  border-top: 30px solid transparent;
  border-bottom: 30px solid transparent;
}
.two:hover:before {
  border: 0px solid transparent;
  width: 50px;
  height: 50px;
  background: white;
}
.four:before {
  content: attr(data-start);
  color: white;
  font-size: 30px;
  opacity: 1;
}
.four:after {
  content: attr(data-end);
  color: white;
  font-size: 30px;
  opacity: 0;
}
.four:hover:before {
  opacity: 0;
}
.four:hover:after {
  opacity: 1;
}
<div class="one"></div>
<div class="two"></div><br/>
<div class="three"><a href="">See here</a>
</div>
<div class="four" data-start="+1" data-end="+2"></div>

是的,我想出了一个类似的外观来表明这种事情仅通过 CSS 是可能的。您会注意到一些差异,其中一些可能是我编码的方式,但您明白了。

原来如此!

注意: Whosebug 的代码片段不喜欢某些 CSS 属性,也不会 运行 它们。这将在 Codepen here 上获得最佳观看效果。

@import url(http://fonts.googleapis.com/css?family=Lato:100,300,400,700);
 body {
  font-family: 'Lato', sans-serif;
  background: #222;
}
.grid {
  width: 600px;
  height: 600px;
  border: 1px solid;
  margin: 0 auto;
}
.box {
  width: 50%;
  height: 50%;
  float: left;
  position: relative;
}
.box:nth-child(1) {
  background: #01FF70;
}
.box:nth-child(2) {
  background: #FFDC00;
}
.box:nth-child(3) {
  background: #0074D9;
}
.box:nth-child(4) {
  background: #FF4136;
  line-height: 300px;
}
/* Ham Burger */

.hamBurger {
  width: 110px;
  height: 16px;
  background: #fff;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  animation: spin 5s infinite;
}
.hamBurger:before,
.hamBurger:after {
  content: "";
  width: 110px;
  height: 16px;
  background: #fff;
  position: absolute;
  left: 0;
}
.hamBurger:before {
  top: -42px;
  animation: translateBefore 5s infinite;
}
.hamBurger:after {
  bottom: -42px;
  animation: translateAfter 5s infinite;
}
@keyframes translateBefore {
  20% {
    transform: rotate(45deg);
    width: 60px;
    left: 52px;
    top: -24px;
  }
  40% {
    transform: rotate(45deg);
    width: 60px;
    left: 52px;
    top: -24px;
  }
  60% {
    transform: rotate(0deg);
    width: 110px;
    left: 0;
    top: -42px;
  }
}
@keyframes translateAfter {
  20% {
    transform: rotate(-45deg);
    width: 60px;
    left: 52px;
    bottom: -24px;
  }
  40% {
    transform: rotate(-45deg);
    width: 60px;
    left: 52px;
    bottom: -24px;
  }
  60% {
    transform: rotate(0deg);
    width: 110px;
    left: 0;
    bottom: -42px;
  }
}
@keyframes spin {
  20% {
    transform: rotate(180deg);
  }
  40% {
    transform: rotate(180deg);
  }
  60% {
    transform: rotate(360deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
/* End of Ham Burger */

/* Refresh */

.refresh {
  width: 100px;
  height: 100px;
  border: 16px solid transparent;
  border-top-color: #fff;
  border-left-color: #fff;
  border-radius: 50%;
  position: relative;
  transform: rotate(-45deg);
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  animation: refreshSpin 1s infinite linear;
}
.refresh:before {
  content: "";
  width: 0;
  height: 0;
  border-left: 30px solid #fff;
  border-top: 30px solid transparent;
  border-bottom: 30px solid transparent;
  position: absolute;
  top: -16px;
  left: 80%;
  transform: rotate(45deg);
}
@keyframes refreshSpin {
  100% {
    transform: rotate(315deg);
  }
}
/* End of Refresh */

/* Numbers */

.plus,
.num1,
.num2 {
  display: inline-block;
  font-size: 100px;
  color: #fff;
}
.plus {
  animation: plusSpin 5s infinite;
  margin-left: 30%;
}
.num1 {
  position: relative;
  animation: num1Effect 5s infinite;
  padding-left: 20px;
}
.num2 {
  position: absolute;
  top: 0;
  background: #FF4136;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  animation: num2Effect 5s infinite;
}
@keyframes num2Effect {
  30% {
    clip-path: polygon(100% 100%, 100% 0%, 100% 100%, 0% 100%);
  }
  70% {
    clip-path: polygon(100% 100%, 100% 0%, 100% 100%, 0% 100%);
  }
}
@keyframes num1Effect {
  30% {
    padding-left: 0px;
  }
  70% {
    padding-left: 0px;
  }
}
@keyframes plusSpin {
  20% {
    transform: rotate(90deg);
  }
  70% {
    transform: rotate(90deg);
  }
  90% {
    transform: rotate(0deg);
  }
}
/* End of Numbers */

/* Icons */

.icons {
  width: 120px;
  height: 120px;
  background: #fff;
  position: absolute;
  top: 27%;
  left: 27%;
  animation: spinIcon 5s infinite;
}
.icons:after {
  content: "";
  display: block;
  height: 100%;
  width: 0px;
  background: #FFDC00;
  margin: 0 auto;
  animation: spinIconMiddle 5s infinite;
}
@keyframes spinIconMiddle {
  33% {
    width: 0;
  }
  66% {
    width: 30px;
  }
  100% {
    width: 0px;
  }
}
@keyframes spinIcon {
  33% {
    transform: rotate(90deg);
  }
  66% {
    transform: rotate(180deg);
  }
  100% {
    transform: rotate(270deg);
  }
}
/* End of Icons */
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="grid">
  <div class="box">
    <div class="hamBurger"></div>
  </div>
  <div class="box">
    <div class="icons"></div>
  </div>
  <div class="box">
    <div class="refresh"></div>
  </div>
  <div class="box">
    <div class="plus">+</div>
    <div class="num1">
      <div class="num2">2</div>1
    </div>

  </div>
</div>

如有任何问题欢迎提问。


补充说明:

  • 我想不出在顶部创建三角形的好方法 不使用 SVG 就对了。所以我省略了那部分。
  • 这是在使用 clip-path,目前还不是很好的支持。查看更多 here.
  • 添加的脚本是为了让这个前缀免费
  • 创建于 Chrome,因此最好在 Chrome 中查看。这远非完美,只是为了证明这是可以做到的。