【www.bbyears.com--css3教程】
本文我们使用keyframe动画和一些小技巧来实现苹果标表盘进度条动画,效果还是比较炫的。
这是效果图如下
拨号进度条
表的动画是由3个线条构成的,每个都是进度条。进度条两边带有圆角。我们将使用一点小技巧来实现。
拨号进度条
我们先来画半个圆。HTML代码如下:
我们使用border-radius属性和keyframe来实现半月形状和旋转动画。
.wedge {
animation: rotate 4s infinite linear;
border-radius: 0 4em 4em 0;
background: red;
width: 2em;
height: 4em;
transform-origin: 0% 50%;
}
@keyframes rotate {
100% {
transform: rotateZ(360deg);
}
}
遮罩
按照往常的做法,我可能会使用CSS3的clip属性。但是由于浏览器内核兼容性问题,我决定还是放弃。这里,我们简单使用overflow:hidden就够了。
这里使用了两个元素,dial-container的宽度只有wedge的一半,而且它设置了overflow为hidden,容器的位置在半圆的右边,并旋转wedge,这样就出现了扇形效果。
.dial-container {
position: absolute;
top: 0;
left: 2em;
width: 2em;
height: 4em;
overflow: hidden;
}
为了画完整个圆,我们需要创建第二个wedge和第二个container,放在左边。
整个圆
我使用了一个wrapper来给两个containers定位。
并使用下面css来处理它们的位置关系。
.wrapper {
position: absolute;
width: 4em;
height: 4em;
left: calc(50% - 2em);
}
.dial-container {
position: absolute;
top: 0;
bottom: 0;
overflow: hidden;
width: 2em;
}
.wedge {
background: red;
height: 4em;
width: 2em;
}
.container1 {
left: 2em;
}
.container1 .wedge {
animation: rotate-bg-1 4s infinite linear;
border-radius: 0 4em 4em 0;
left: 0;
transform-origin: 0 50%;
}
.container2 {
left: 0;
}
.container2 .wedge {
animation: rotate-bg-2 4s infinite linear;
border-radius: 4em 0 0 4em;
transform-origin: 2em 2em;
}
/* First animation moves 180 degrees in the first 2 seconds */
@keyframes rotate-bg-1 {
50%, 100% {
transform: rotateZ(180deg);
}
}
/* Second animation moves 180 degrees in the last 2 seconds */
@keyframes rotate-bg-2 {
0%, 50% {
transform: rotateZ(0);
}
100% {
transform: rotateZ(180deg);
}
}
运行结果:
进度
下一步是让wedge变成进度条。我们可以使用伪类在中间画个圆圈遮盖掉。
.wrapper::after {
content: "";
background: #fff;
border-radius: 50%;
width: 3em;
height: 3em;
position: absolute;
top: 0.5em;
left: 0.5em;
}
现在看起来有点进度条的样子了。
边缘处理
苹果表动画看起来很柔和还跟它的圆角有关。要创建这样的圆角,在weget上用css属性时不行的。不过我们可以使用点小技巧。
start元素和end元素是两个多余的元素用来放在进度条的开始和结尾(这样就生成圆角了!)
.marker {
background: green;
border-radius: 50%;
height: 0.5em;
width: 0.5em;
position: absolute;
top: 0;
left: calc(50% - 0.25em);
}
.end {
animation: rotate-marker 4s infinite linear;
transform-origin: 50% 2em;
}
@keyframes rotate-marker {
100% {
transform: rotateZ(360deg);
}
}
上面的css把end圆设成绿色。并把transform-origin设置成容器中点。
整合到一起
html
Activity 10:09
SCSS
@import "http://fonts.googleapis.com/css?family=Varela+Round|Open+Sans"; $path: "http://www.w3cplus.com/sites/default/files/blogs/2015/1507"; .watch-container { background: #fff; padding: 1em 1.5em 2.75em 1em } .watch { background: url(#{$path}/watchbg.jpg) no-repeat; background-size: 100%; font-family: "San Francisco Display UltraLight","Open Sans",Helvetica,Arial,Serif; font-size: 16px; width: 220px; height: 244px; position: relative; margin: 50px auto; } .screen { width: 59.2%; height: 74%; position: absolute; left: 18%; top: 13%; .title, .time { animation: show-title 5s infinite ease-out; color: #b1b4c2; font-size: 0.9em; position: absolute; top: 0; left: 0; letter-spacing: 0.05em; } .time { animation-delay: 0.2s; right: 0; left: auto; } .dials { animation: show-dials 5s infinite ease-out; width: 4em; height: 4em; border-radius: 50% ; position: absolute; top: 1.75em; left: 0; } } .dial { border: 1px solid #000; border-radius: 50%; &.move { position: absolute; width: 8em; height: 8em; &:before { background: url(#{$path}/1.png) no-repeat center; background-size: 50%; content: ""; width: 1.5em; height: 1.5em; position: absolute; top: -0.35em; left: calc(50% - 0.75em); z-index: 10; } &:after { content: ""; background: #000; border-radius: 50%; width: 6em; height: 6em; position: absolute; top: 1em; left: 1em; } } &.exercise { position: absolute; width: 6em; height: 6em; top: 1em; left: 1em; &:before { background: url(#{$path}/2.png) no-repeat center; background-size: 50%; content: ""; width: 1.5em; height: 1.5em; position: absolute; top: -0.35em; left: calc(50% - 0.75em); z-index: 10; } &:after { content: ""; background: #000; border-radius: 50%; width: 4em; height: 4em; position: absolute; top: 1em; left: 1em } } &.stand { position: absolute; width: 4em; height: 4em; top: 2em; left: 2em; &:before { background: url(#{$path}/3.png) no-repeat center; background-size: 50%; content: ""; width: 1.5em; height: 1.5em; position: absolute; top: -0.35em; left: calc(50% - 0.75em); z-index: 10 } &:after { content: ""; background: #000; border-radius: 50%; width: 2em; height: 2em; position: absolute; top: 1em; left: 1em } } } .dial-container { position: absolute; top: 0; bottom: 0; width: 4em; overflow: hidden; &.container1 { left: 4em; } &.container2 { left: 0; } .dial.exercise & { position: absolute; top: 0; bottom: 0; width: 3em; overflow: hidden; } } .wedge { width: 4em; height: 8em; position: absolute; top: 0; left: 0; .container1 &{ animation: rotate-bg-dial-1-1 5s 0.2s linear infinite; border-radius: 8em 0 0 8em; background: #fc1d20; left: -4em; transform-origin: 100% 50% } .container2 &{ animation: rotate-bg-dial-1-2 5s 0.2s linear infinite; background: #fc1d20; border-radius: 0 8em 8em 0; transform-origin: 0 50%; left: 4em; } .dial.exercise & { border-radius: 50%; width: 3em; height: 6em; position: absolute; } } .marker { width: 1em; height: 1em; background: #fc1d20; border-radius: 50%; position: absolute; top: 0; left: calc(50% - 0.5em) } .end { animation: rotate-marker-dial-1 5s 0.2s linear infinite; transform-origin: 50% 4em } .dial.exercise{ .container1 { left: 3em; .wedge { animation: rotate-bg-dial-2-1 5s .5s linear infinite; border-radius: 8em 0 0 8em; position: absolute; background: #9cfc33; left: -3em; transform-origin: 100% 50%; } } .marker { width: 1em; height: 1em; background: #9cfc33; border-radius: 50%; position: absolute; top: 0; left: calc(50% - 0.48em); } .end { animation: rotate-marker-dial-2 5s .5s linear infinite; transform-origin: 45% 3em; } } .dial.stand { .dial-container { position: absolute; top: 0; bottom: 0; width: 4em; overflow: hidden; } .wedge { border-radius: 50%; width: 2em; height: 4em; position: absolute; } .container1 { left: 2em; .wedge { position: absolute; animation: rotate-bg-dial-3-1 5s 0.5s linear infinite; background: #32cbd4; border-radius: 8em 0 0 8em; left: -2em; transform-origin: 100% 50%; } } .marker { width: 1em; height: 1em; background: #32cbd4; border-radius: 50%; position: absolute; top: 0; left: calc(50% - 0.5em); } .end { animation: rotate-marker-dial-3 5s 0.5s linear infinite; transform-origin: 50% 2em; } } .dial-background { position: absolute; top: 0; right: 0; bottom: 0; left: 0; border-radius: 50%; &.one { background: #400818; } &.two { background: #2d400c; } &.three { background: #163d3b } } .pips { animation: show-dials 5s 0.1s infinite ease-out; position: absolute; bottom: 0; left: calc(50% - 1em); width: 2em; div { width: 0.25em; height: 0.25em; background-color: #353535; border-radius: 50%; display: inline-block; margin: 0 0.02em; &:first-child { background-color: #fff } } } @keyframes rotate-marker-dial-1 { 0%,6% { transform: none } 28%,94% { transform: rotateZ(220deg) } 95%,100% { transform: none } } @keyframes rotate-bg-dial-1-1 { 0%,6% { transform: rotateZ(0) } 24%,94% { transform: rotateZ(180deg) } 95%,100% { transform: rotateZ(0) } } @keyframes rotate-bg-dial-1-2 { 24% { transform: rotateZ(0) } 28%,94% { transform: rotateZ(40deg) } 95%,100% { transform: rotateZ(0) } } @keyframes rotate-marker-dial-2 { 20%,90% { transform: rotateZ(160deg) } 91%,100% { transform: none } } @keyframes rotate-bg-dial-2-1 { 0%,0.5% { transform: none } 19%,90% { transform: rotateZ(160deg) } 91%,100% { transform: none } } @keyframes rotate-marker-dial-3 { 19%,90% { transform: rotateZ(90deg) } 91%,100% { transform: none } } @keyframes rotate-bg-dial-3-1 { 0%,1% { transform: none } 19%,90% { transform: rotateZ(90deg) } 91%,100% { transform: none } } @keyframes show-title { 0% { transform: translateY(0.25em); opacity: 0 } 10%,95% { transform: translateY(0); opacity: 1 } 100% { transform: translateY(0.25em); opacity: 0 } } @keyframes show-dials { 0%,8% { opacity: 0; transform: translateY(0.25em) } 15%,93% { opacity: 1; transform: none } 100% { opacity: 0; transform: translateY(0.25em) } }