我正在制作一个使用“齿轮和链条”的 CSS 动画,但无法创建“平滑”的边框旋转序列。
你可以在这个fiddle中看到我(目前)如何使用伪元素来生成“旋转”效果。这是通过在白色虚线和金色虚线边框之间“切换”来完成的,使其看起来像是“边框在旋转”。
我有什么
#one{
-webkit-animation: rotateClockwiseAnimation 5s linear infinite; /* Safari 4+ */
-moz-animation: rotateClockwiseAnimation 5s linear infinite; /* Fx 5+ */
-o-animation: rotateClockwiseAnimation 5s linear infinite; /* Opera 12+ */
animation: rotateClockwiseAnimation 5s linear infinite; /* IE 10+, Fx 29+ */
}
#two{
-webkit-animation: rotateAntiClockwiseAnimation 5s linear infinite; /* Safari 4+ */
-moz-animation: rotateAntiClockwiseAnimation 5s linear infinite; /* Fx 5+ */
-o-animation: rotateAntiClockwiseAnimation 5s linear infinite; /* Opera 12+ */
animation: rotateAntiClockwiseAnimation 5s linear infinite; /* IE 10+, Fx 29+ */
position:absolute;
top:30px;
left:42px;
width:80px;
}
@-webkit-keyframes rotateClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@-moz-keyframes rotateClockwiseAnimation{
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@-o-keyframes rotateClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes rotateClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@-webkit-keyframes rotateAntiClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(-360deg); }
}
@-moz-keyframes rotateAntiClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(-360deg); }
}
@-o-keyframes rotateAntiClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(-360deg); }
}
@keyframes rotateAntiClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(-360deg); }
}
/******************************************************************************/
.chain{
height:70px;
width:80%;
border:5px dashed gold;
border-radius:30px;
position:absolute;
top:30px;
left:40px;
-webkit-animation: switchGoldBlackBorder 0.8s infinite; /* Safari 4+ */
-moz-animation: switchGoldBlackBorder 0.8s infinite; /* Fx 5+ */
-o-animation: switchGoldBlackBorder 0.8s infinite; /* Opera 12+ */
animation: switchGoldBlackBorder 0.8s infinite; /* IE 10+, Fx 29+ */
}
@-webkit-keyframes switchBlackGoldBorder {
0% { border: 5px dashed transparent; }
49% { border: 5px dashed transparent; }
50% { border: 5px dashed gold; }
100% { border: 5px dashed gold; }
}
@-moz-keyframes switchBlackGoldBorder{
0% { border: 5px dashed transparent; }
49% { border: 5px dashed transparent; }
50% { border: 5px dashed gold; }
100% { border: 5px dashed gold; }
}
@-o-keyframes switchBlackGoldBorder {
0% { border: 5px dashed transparent; }
49% { border: 5px dashed transparent; }
50% { border: 5px dashed gold; }
100% { border: 5px dashed gold; }
}
@keyframes switchBlackGoldBorder {
0% { border: 5px dashed transparent; }
49% { border: 5px dashed transparent; }
50% { border: 5px dashed gold; }
100% { border: 5px dashed gold; }
}
.chain:after{
content:"";
position:absolute;
height:70px;
border-radius:30px;
width:100%;
top:-5px;
left:-5px;
border:5px solid gold;
z-index:-1;
-webkit-animation: switchBlackGoldBorder 0.8s infinite; /* Safari 4+ */
-moz-animation: switchBlackGoldBorder 0.8s infinite; /* Fx 5+ */
-o-animation: switchBlackGoldBorder 0.8s infinite; /* Opera 12+ */
animation: switchBlackGoldBorder 0.8s infinite; /* IE 10+, Fx 29+ */
}
@-webkit-keyframes switchGoldBlackBorder {
0% { border: 5px solid gold; }
49% { border: 5px solid gold; }
50% { border: 5px solid white; }
100% { border: 5px solid white; }
}
@-moz-keyframes switchGoldBlackBorder{
0% { border: 5px solid gold; }
49% { border: 5px solid gold; }
50% { border: 5px solid white; }
100% { border: 5px solid white; }
}
@-o-keyframes switchGoldBlackBorder {
0% { border: 5px solid gold; }
49% { border: 5px solid gold; }
50% { border: 5px solid white; }
100% { border: 5px solid white; }
}
@keyframes switchGoldBlackBorder {
0% { border: 5px solid gold; }
49% { border: 5px solid gold; }
50% { border: 5px solid white; }
100% { border: 5px solid white; }
}
<svg id="one" style="width:50px" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 100">
<defs>
<circle id="c" cx="50" cy="50" r="30" stroke="#808080" fill="none" stroke-width="25"/>
<path id="d" stroke="#808080" stroke-width="16" d="M50 0, V15 M50 100, V85 M0 50, H15 M100 50, H85"/>
</defs>
<use xlink:href="#c"/>
<use xlink:href="#d"/>
<use xlink:href="#d" transform="rotate(45, 50, 50)"/>
</svg>
<svg id="two" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 100">
<use xlink:href="#one"/>
</svg>
<div class="chain"></div>
因此,在代码片段的下半部分,您可以看到我是如何通过使用关键帧生成“旋转链效果”的。
我想要什么
我的总体愿望是生成如下内容:
想一想传送带的横截面,以及“末端的齿轮如何驱动传送带”。我正在尝试重现这一点。 (即虚线边框的金色部分应该在齿轮的槽内,并被它“拉动”)
#one{
-webkit-animation: rotateClockwiseAnimation 5s linear infinite; /* Safari 4+ */
-moz-animation: rotateClockwiseAnimation 5s linear infinite; /* Fx 5+ */
-o-animation: rotateClockwiseAnimation 5s linear infinite; /* Opera 12+ */
animation: rotateClockwiseAnimation 5s linear infinite; /* IE 10+, Fx 29+ */
border:5px dashed gold;
border-radius:50%;
}
@-webkit-keyframes rotateClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@-moz-keyframes rotateClockwiseAnimation{
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@-o-keyframes rotateClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes rotateClockwiseAnimation {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
<svg id="one" style="width:50px" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 100">
<defs>
<circle id="c" cx="50" cy="50" r="30" stroke="#808080" fill="none" stroke-width="25"/>
<path id="d" stroke="#808080" stroke-width="16" d="M50 0, V15 M50 100, V85 M0 50, H15 M100 50, H85"/>
</defs>
<use xlink:href="#c"/>
<use xlink:href="#d"/>
<use xlink:href="#d" transform="rotate(45, 50, 50)"/>
</svg>
但金色破折号适合齿轮的凹槽,并且占屏幕宽度的 80%(如果这有意义的话)。
最后,我想生成像这张图片描绘的东西:
看到我希望链条如何“旋转”了吗?
我当前的问题
- 由于动画是通过使用伪元素“破解”的,我发现很难真正同步这个“链”的旋转。
- 我仍在学习关键帧动画,所以我确定这不是最好的方法
- 同样,svg 对我来说是一个新概念,所以请原谅我不愿意使用它(这就是为什么我将 css 用于“链”)
- 最后,我想“让它看起来像”齿轮在转动链条,但现在它们看起来完全(而且做得很糟糕)独立的元素动画
最佳答案
齿轮和链条动画:
我完全重构了代码(CSS 和 HTML),现在是:
- 更短(尤其是 css)
- 更简单
- 更现实:更正了链条和齿轮之间的同步问题,并在右侧添加了一个缺失的齿轮,因为您的链条似乎漂浮在空中:
方法是相同的,为齿轮和 dash-offset
设置旋转 Angular 动画对于链路径。我调整了两个动画之间的时间,让它看起来好像齿轮在拉动链条。
浏览器支持:
作为 IE doesn't support svg 动画元素我还用 snap.svg 制作了这个版本的动画也支持 IE9 及更高版本的库(在 IE9 中使用 crossbrowsertesting 进行测试)。
DEMO 支持 IE
var cont = new Snap('#svg'),
chain = cont.select('#chain'),
cogAcw = cont.select('#cog_acw'),
cogCw = cont.select('#cog_cw'),
speed = 500; // Lower this number to make the animation faster
function infChain(el) {
var len = el.getTotalLength();
el.attr({"stroke-dasharray": len/62,"stroke-dashoffset": 0});
el.animate({"stroke-dashoffset": -len/31}, speed, mina.linear, infChain.bind(null, el));
}
function rotateAcw(el) {
el.transform('r22.5,20,20');
el.animate({ transform: 'r-22.5,20,20' }, speed, mina.linear, rotateAcw.bind( null, el));
}
function rotateCw(el) {
el.transform('r0,20,20');
el.animate({ transform: 'r45,20,20' }, speed, mina.linear, rotateCw.bind( null, el));
}
infChain(chain);
rotateAcw(cogAcw);
rotateCw(cogCw);
svg {
width:100%;
}
<script src="http://thisisa.simple-url.com/js/snapsvg.js"></script>
<svg id="svg" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 30">
<defs>
<circle id="c" cx="20" cy="20" r="4" stroke="#808080" fill="none" stroke-width="4" />
<path id="d" stroke="#808080" stroke-width="2" d="M20 13 V16 M27 20 H24 M20 27 V24 M13 20 H16" />
<g id="cog_acw">
<use xlink:href="#c" /><use xlink:href="#d" />
<use xlink:href="#d" transform="rotate(45 20 20)" />
</g>
<g id="cog_cw">
<use xlink:href="#c" /><use xlink:href="#d" />
<use xlink:href="#d" transform="rotate(45 20 20)" />
</g>
</defs>
<path id="chain" stroke-width="1" stroke="#000" fill="transparent"
d="M21.3 13.5 H20 C11.4 13.5 11.4 26.5 20 26.5 H80 C89.4 26.5 89.4 13.5 80.8 13.5z" />
<use xlink:href="#cog_acw" />
<use transform="translate(60.5 0), rotate(19,20,20)" xlink:href="#cog_acw" />
<use transform="translate(-4.5 -4.5),scale(.8), rotate(0,20,20)" xlink:href="#cog_cw" />
</svg>
svg{width:100%;}
#chain_st{
-webkit-animation: dash 1s infinite linear;
-moz-animation: dash 1s infinite linear;
-o-animation: dash 1s infinite linear;
animation: dash 1s infinite linear;
}
@-webkit-keyframes dash {
to { stroke-dashoffset: -5; }
}
@-moz-keyframes dash {
to { stroke-dashoffset: -5; }
}
@-o-keyframes dash {
to { stroke-dashoffset: -5; }
}
@keyframes dash {
to { stroke-dashoffset: -5; }
}
<svg id="one" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 30">
<defs>
<circle id="c" cx="20" cy="20" r="4" stroke="#808080" fill="none" stroke-width="4"/>
<path id="d" stroke="#808080" stroke-width="2" d="M20 13 V16 M27 20 H24 M20 27 V24 M13 20 H16"/>
<g id="cog">
<use xlink:href="#c"/>
<use xlink:href="#d"/>
<use xlink:href="#d" transform="rotate(45 20 20)"/>
</g>
</defs>
<g transform="translate(0,-7), scale(0.8), rotate(22.5 8 8)">
<use xlink:href="#cog">
<animateTransform attributeType="xml" attributeName="transform" type="rotate" from="-22.5 20 20" to="337.5 20 20" dur="8s" repeatCount="indefinite"/>
</use>
</g>
<path id="chain_st" stroke-width="1" stroke="#000" fill="transparent" stroke-dasharray="2.6 2.45" d="M21.3 13.5 H20 C11.4 13.5 11.4 26.5 20 26.5 H80 C89 26.5 89 13.5 80.8 13.5z" />
<use class="rot" xlink:href="#cog">
<animateTransform attributeType="xml" attributeName="transform" type="rotate"from="22.5 20 20" to="-337.5 20 20" dur="8s" repeatCount="indefinite"/>
</use>
<g transform="translate(60.3 0)">
<use class="" xlink:href="#cog">
<animateTransform attributeType="xml" attributeName="transform" type="rotate" from="22.5 20 20" to="-337.5 20 20" dur="8s" repeatCount="indefinite"/>
</use>
</g>
</svg>
原始答案:
您可以使用其他 svg 虚线路径并使用关键帧动画为 dash-offset 属性设置动画。
这可以而且应该针对“真实世界”使用进行简化/调整:
- 所有元素都可以包含在一个
<svg>
中标签(这会使它更简单,两个齿轮 + 链可以一起调整大小) - 链条和齿轮之间的同步并不完美,需要调整链条的速度/尺寸。
#one {
-webkit-animation: rotateClockwiseAnimation 5s linear infinite;
/* Safari 4+ */
-moz-animation: rotateClockwiseAnimation 5s linear infinite;
/* Fx 5+ */
-o-animation: rotateClockwiseAnimation 5s linear infinite;
/* Opera 12+ */
animation: rotateClockwiseAnimation 5s linear infinite;
/* IE 10+, Fx 29+ */
}
#two {
-webkit-animation: rotateAntiClockwiseAnimation 5s linear infinite;
/* Safari 4+ */
-moz-animation: rotateAntiClockwiseAnimation 5s linear infinite;
/* Fx 5+ */
-o-animation: rotateAntiClockwiseAnimation 5s linear infinite;
/* Opera 12+ */
animation: rotateAntiClockwiseAnimation 5s linear infinite;
/* IE 10+, Fx 29+ */
position: absolute;
top: 30px;
left: 42px;
width: 80px;
}
@-webkit-keyframes rotateClockwiseAnimation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@-moz-keyframes rotateClockwiseAnimation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@-o-keyframes rotateClockwiseAnimation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes rotateClockwiseAnimation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@-webkit-keyframes rotateAntiClockwiseAnimation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
@-moz-keyframes rotateAntiClockwiseAnimation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
@-o-keyframes rotateAntiClockwiseAnimation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
@keyframes rotateAntiClockwiseAnimation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
/******************************************************************************/
#chain {
width: 650px;
position: absolute;
top: 24px;
left: 35px;
}
.chain_st {
stroke-dasharray: 1.5;
stroke-dashoffset: 10;
-webkit-animation: dash 18s infinite linear;
-moz-animation: dash 18s infinite linear;
-o-animation: dash 18s infinite linear;
animation: dash 18s infinite linear;
}
@-webkit-keyframes dash {
to {
stroke-dashoffset: 100;
}
}
@-moz-keyframes dash {
to {
stroke-dashoffset: 100;
}
}
@-o-keyframes dash {
to {
stroke-dashoffset: 100;
}
}
keyframes dash {
to {
stroke-dashoffset: 100;
}
}
<svg id="one" style="width:50px" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 100">
<defs>
<circle id="c" cx="50" cy="50" r="30" stroke="#808080" fill="none" stroke-width="25" />
<path id="d" stroke="#808080" stroke-width="16" d="M50 0, V15 M50 100, V85 M0 50, H15 M100 50, H85" />
</defs>
<use xlink:href="#c" />
<use xlink:href="#d" />
<use xlink:href="#d" transform="rotate(45, 50, 50)" />
</svg>
<svg id="two" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 100">
<use xlink:href="#one" />
</svg>
<svg id="chain" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 70 10">
<path class="chain_st" stroke-width="0.5" stroke="#000" fill="transparent" d="M60 1 Q65 1 65 5 Q65 9 60 9 H6 Q1 9 1 5 Q1 1 6 1z" />
</svg>
关于css - 如何制作像 'marching ants'这样平滑的虚线边框旋转动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28693659/