在 Javascript/CSS 中实现图标变形动画?
Implement Icon morph animation in Javascript/CSS?
观看此视频
(高清视频here)
我想知道在 Javascript/CSS 中是否有更简单的方法来实现它。
我知道有一些 CSS3 属性,例如 transition
、animation
、transform
等等,但据我所知,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 中查看。这远非完美,只是为了证明这是可以做到的。
观看此视频
(高清视频here)
我想知道在 Javascript/CSS 中是否有更简单的方法来实现它。
我知道有一些 CSS3 属性,例如 transition
、animation
、transform
等等,但据我所知,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 中查看。这远非完美,只是为了证明这是可以做到的。