web-dev-qa-db-ja.com

「蟻の行進」のような滑らかな破線のボーダー回転アニメーションを作成する方法

「歯車とチェーン」を使用する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%を確保します(それが理にかなっている場合)。

最後に、この画像が描くようなものを生成したいと思います。

enter image description here

チェーンを「回転」させる方法を参照してください?


私の現在の問題

  • アニメーションは擬似要素を使用して「ハッキング」されるため、この「チェーン」の回転を実際に同期させるのは非常に難しいことがわかりました。
  • 私はまだキーフレームアニメーションを学んでいるので、これが最善の方法ではないと確信しています。
  • 繰り返しになりますが、svgは私にとって新しい概念なので、使用することに抵抗があります(そのため、「チェーン」にcssを使用している理由)
  • 最後に、ギアがチェーンを回しているように「見た目を変えたい」のですが、今は完全に(そしてひどく行われている)別の要素のアニメーションのように見えます

47
jbutler483

コグとチェーンのアニメーション:

コードを完全にリファクタリングしました([〜#〜] css [〜#〜]および[〜#〜] html [〜#〜])、それは今です:

  • より短い(特にcss)
  • よりシンプル
  • より現実的な:チェーンが空中に浮いているように見えるため、チェーンとコグの間の同期の問題を修正し、右側に欠落しているコグを追加しました。

[〜#〜] demo [〜#〜]

アプローチは同じで、歯車の回転角度とチェーンパスのdash-offsetをアニメーション化します。歯車がチェーンを引っ張っているように見えるように、両方のアニメーションのタイミングを微調整しました。

ブラウザのサポート:

As IE サポートしない svgアニメーション要素)また、このバージョンのアニメーションも snap.svg をサポートするライブラリで作成しました。 IE9以上(IE9では crossbrowsertesting でテスト済み)。

[〜#〜] demo [〜#〜]with 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プロパティをアニメーション化できます。

これは、「現実の世界」での使用のために単純化/微調整することができます。

  • すべての要素を1つの<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>
77
web-tiki

このアプローチはどうですか?ギアとコンベアの両方にSVGを使用しています。ギアは例に従って回転しますが、私はstroke-dasharrayとアニメーションstroke-dash-offsetコンベアベルトを動かします。

コンベアの長さとダッシュのタイミングを正しくするのに少し手間がかかりました。ギアのサイズやコンベアの長さを変更する場合は、微調整する必要があります。

#one{
  -webkit-animation: rotateClockwiseAnimation 4s linear infinite; /* Safari 4+ */
  -moz-animation:    rotateClockwiseAnimation 4s linear infinite; /* Fx 5+ */
  -o-animation:      rotateClockwiseAnimation 4s linear infinite; /* Opera 12+ */
  animation:         rotateClockwiseAnimation 4s linear infinite; /* IE 10+, Fx 29+ */

}
#two{
  -webkit-animation: rotateAntiClockwiseAnimation 4s linear infinite; /* Safari 4+ */
  -moz-animation:    rotateAntiClockwiseAnimation 4s linear infinite; /* Fx 5+ */
  -o-animation:      rotateAntiClockwiseAnimation 4s linear infinite; /* Opera 12+ */
  animation:         rotateAntiClockwiseAnimation 4s 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
{
  -webkit-animation: conveyor 0.5s linear infinite; /* Safari 4+ */
  -moz-animation:    conveyor 0.5s linear infinite; /* Fx 5+ */
  -o-animation:      conveyor 0.5s linear infinite; /* Opera 12+ */
  animation:         conveyor 0.5s linear infinite; /* IE 10+, Fx 29+ */
}


@-webkit-keyframes conveyor {
    0%   { stroke-dashoffset: -9; }
    100% { stroke-dashoffset: 20.06; }
}
@-moz-keyframes conveyor {
    0%   { stroke-dashoffset: -9; }
    100% { stroke-dashoffset: 20.06; }
}
@-o-keyframes conveyor {
    0%   { stroke-dashoffset: -9; }
    100% { stroke-dashoffset: 20.06; }
}
@keyframes conveyor {  
    0%   { stroke-dashoffset: -9; }
    100% { stroke-dashoffset: 20.06; }
}
<svg width="100%" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 800 100">
    <defs>
        <circle id="c" cx="0" cy="0" r="30" stroke="#808080" fill="none" stroke-width="25"/>
        <path id="d" stroke="#808080" stroke-width="16" d="M0,-50 v15 M0,50 v-15 M-50,0 h15 M50,0 h-15"/>

        <g id="gear">
          <use xlink:href="#c"/>
          <use xlink:href="#d"/>
          <use xlink:href="#d" transform="rotate(45)"/>
        </g>
    </defs>
  
  <rect id="chain2"
          x="43" y="23" width="598" height="74" rx="37"
          stroke="gold" stroke-width="2" fill="none"/>

    <g transform="translate(27,27) scale(0.5)">
      <g id="one">
        <use xlink:href="#gear"/>
      </g>
    </g>

    <g transform="translate(80,60) scale(0.8)">
      <g id="two">
        <use xlink:href="#gear"/>
      </g>
    </g>
  
  <rect id="chain"
          x="43" y="23" width="598" height="74" rx="37"
          stroke="gold" stroke-width="5" fill="none"
          stroke-dasharray="14 15.06"/>
</svg>
29
Paul LeBeau

注:破線の境界線を使用すると、すべてのブラウザーで一貫した出力が得られないため、アニメーション全体をボックスシャドウで再作成しました。

ワーキング

.. and Works cross-browser。
FF 5 +、GC 4 +、IE9 +、Safari 4 +、Opera 12.1 +

あなたはbox-shadowを使用してこれを試すことができます:

  • 歯車の歯を作成するには、負の広がり半径を持つボックスシャドウを使用します。たとえば、ギアのサイズは_50px_でした。そのため、_box-shadow_を_d=8px_で丸めるには、_-46px_をスプレッド半径として使用しました。

  • 座標ジオを使用して歯を配置し、単純化するために8本の歯のみを使用しました。

  • ストレートコンベヤの場合、歯間の距離を知る必要があります。次のようにして取得します。

  • 2*pi*(gear radius) / no. of teeth = _(pi * r) / 4_
    Mine= _(55 * 3.1415) / 4 = 43_(約)
    歯の半径は4pxで、ギアの円周から1px離れているため、半径を55としました。

  • 上下の直線コンベアを整列させるには、距離の倍数だけ平行移動する必要があります。ギアについては、43pxで翻訳します。

足場

[〜#〜] fiddle [〜#〜]

_body {
    background: rgba(25,80,175, 0.4);
}
.rect {
    height: 116px;
    width: 401px;
    border-radius: 58px;
    position: relative;
    overflow: hidden;
}

.rect:before, .rect:after {
    content: '';
    position: absolute;
    left: 46px; /*50-half width*/
    height: 8px;
    width: 8px;
    border-radius: 50%;
    background: transparent;
    box-shadow: 43px 0 0 0 white, 86px 0 0 0 white, 129px 0 0 0 white, 172px 0 0 0 white, 215px 0 0 0 white, 258px 0 0 0 white, 301px 0 0 0 white;
    -webkit-animation: Apple 0.3s linear infinite;
    -moz-animation: Apple 0.3s linear infinite;
    animation: Apple 0.3s linear infinite;
}
.rect:before {
    top: 0px;
}
.rect:after {
    bottom: 0px;
    -webkit-animation-direction: reverse;
    -moz-animation-direction: reverse;
    animation-direction: reverse;
}
@-webkit-keyframes Apple {
    0% {-webkit-transform: translatex(0px);}
    100% {-webkit-transform: translateX(-43px);}
}
@-moz-keyframes Apple {
    0% {-moz-transform: translatex(0px);}
    100% {-moz-transform: translateX(-43px);}
}
@keyframes Apple {
    0% {transform: translatex(0px);}
    100% {transform: translateX(-43px);}
}
.left, .right {
    content: '';
    position: relative;
    height: 100px;
    width: 100px;
    border-radius: 50px;
    background-color: #222;
    box-shadow: 0 55px 0 -46px white, 55px 0 0 -46px white, 0 -55px 0 -46px white, -55px 0 0 -46px white,
        39px 39px 0 -46px white, -39px -39px 0 -46px white, 39px -39px 0 -46px white, -39px 39px 0 -46px white;
    -webkit-animation: mango 2.4s linear infinite;
    -moz-animation: mango 2.4s linear infinite;
    animation: mango 2.4s linear infinite;
}
.left {
    top: -108px;
    left: 0px;
}
.right {
    top: -208px;
    left: 301px;
}
@-webkit-keyframes mango {
    0% {-webkit-transform: rotate(0deg);}
    100% {-webkit-transform: rotate(-360deg);}
}
@-moz-keyframes mango {
    0% {-moz-transform: rotate(0deg);}
    100% {-moz-transform: rotate(-360deg);}
}
@keyframes mango {
    0% {transform: rotate(0deg);}
    100% {transform: rotate(-360deg);}
}_
_<div class="rect"></div>
<div class="left"></div>
<div class="right"></div>_

最終版

...ギア付きチェーンは現在 点在 破線!

[〜#〜] fiddle [〜#〜]

_body {
    background-color: white;
}
.rect {
    height: 120px;
    width: 401px;
    border-radius: 58px;
    position: relative;
}

.rect:before, .rect:after {
    content: '';
    position: absolute;
    left: 40px; /*50-half width*/
    height: 10px;
    width: 20px;
    background: transparent;
    box-shadow: 43px 0 0 0 gold, 86px 0 0 0 gold, 129px 0 0 0 gold, 172px 0 0 0 gold, 215px 0 0 0 gold, 258px 0 0 0 gold, 301px 0 0 0 gold, 344px 0 0 0 gold; /*keep adding 43 to x-axis*/
    -webkit-animation: Apple 0.6s linear infinite;
    -moz-animation: Apple 0.6s linear infinite;
    animation: Apple 0.6s linear infinite;
    overflow: hidden;
}
.rect:before {
    top: 0px;
}
.rect:after {
    bottom: 0px;
    -webkit-animation-direction: reverse;
    -moz-animation-direction: reverse;
    animation-direction: reverse;
}
@-webkit-keyframes Apple {
    0% {-webkit-transform: translatex(0px);}
    100% {-webkit-transform: translateX(-43px);}
}
@-moz-keyframes Apple {
    0% {-moz-transform: translatex(0px);}
    100% {-moz-transform: translateX(-43px);}
}
@keyframes Apple {
    0% {transform: translatex(0px);}
    100% {transform: translateX(-43px);}
}
.left, .right {
    content: '';
    position: relative;
    height: 100px;
    width: 100px;
    border-radius: 50px;
    -webkit-animation: mango 4.8s linear infinite;
    -moz-animation: mango 4.8s linear infinite;
    animation: mango 4.8s linear infinite;
}
.left {
    top: -110px;
    left: 0px;
}
.right {
    top: -210px;
    left: 344px;
}
.left:before, .left:after, .right:before, .right:after {
    height: 20px;
    width: 20px;
    content: '';
    position: absolute;
    background-color: gold;
}
.left:before, .right:before {
    box-shadow: 50px 50px 0 0 gold, -50px 50px 0 0 gold, 0 100px 0 0 gold;
    top: -10px;
    left: 40px;
}
.left:after, .right:after {
    transform: rotate(45deg);
    top: 5px;
    left: 76px;
    box-shadow: 0px 100px 0 0 gold, 50px 50px 0 0 gold, -50px 50px 0 0 gold;
}
@-webkit-keyframes mango {
    0% {-webkit-transform: rotate(0deg);}
    100% {-webkit-transform: rotate(-360deg);}
}
@-moz-keyframes mango {
    0% {-moz-transform: rotate(0deg);}
    100% {-moz-transform: rotate(-360deg);}
}
@keyframes mango {
    0% {transform: rotate(0deg);}
    100% {transform: rotate(-360deg);}
}
.cover {
    height: 104px;
    width: 446px;
    border-radius: 50px;
    position: relative;
    background: rgba(255,255,255,1);
    top: -312px;
    left; -2px;
    
}
.gear, .gear2 {
    height: 100px;
    width: 100px;
    background: dimgray;
    border-radius: 50%;
    position: relative;
    -webkit-animation: gear 4.8s linear infinite;
    -moz-animation: gear 4.8s linear infinite;
    animation: gear 4.8s linear infinite;
}
.gear {
    top: -414px;
  
}
.gear2 {
    top: -514px;
    left: 345px;
}
.gear:before, .gear:after, .gear2:before, .gear2:after {
    height: 20px;
    width: 20px;
    content: '';
    position: absolute;
    background-color: dimgray;
    
}
.gear:before, .gear2:before {
    box-shadow: 50px 50px 0 0 dimgray, -50px 50px 0 0 dimgray, 0 100px 0 0 dimgray;
    top: -10px;
    left: 40px;
}
.gear:after, .gear2:after {
    transform: rotate(45deg);
    top: 5px;
    left: 76px;
    box-shadow: 0px 100px 0 0 dimgray, 50px 50px 0 0 dimgray, -50px 50px 0 0 dimgray;
}
@-webkit-keyframes gear {
    0% {-webkit-transform: rotate(22.5deg);}
    100% {-webkit-transform: rotate(-337.5deg);}
}
@-moz-keyframes gear {
    0% {-moz-transform: rotate(22.5deg);}
    100% {-moz-transform: rotate(-337.5deg);}
}
@keyframes gear {
    0% {transform: rotate(22.5deg);}
    100% {transform: rotate(-337.5deg);}
}_
_<div class="rect"></div>
<div class="left"></div>
<div class="right"></div>
<div class="cover"></div>
<div class="gear"></div>
<div class="gear2"></div>_

最終バージョン(丸歯)

_.rect {
    height: 120px;
    width: 401px;
    border-radius: 58px;
    position: relative;
}
.rect:before, .rect:after {
    content: '';
    position: absolute;
    left: 40px; /*50-half width*/
    height: 10px;
    width: 20px;
    box-shadow: 43px 0 0 0 gold, 86px 0 0 0 gold, 129px 0 0 0 gold, 172px 0 0 0 gold, 215px 0 0 0 gold, 258px 0 0 0 gold, 301px 0 0 0 gold, 344px 0 0 0 gold; /*keep adding 43 to x-axis*/
    -webkit-animation: translate 0.6s linear infinite;
    -moz-animation: translate 0.6s linear infinite;
    animation: translate 0.6s linear infinite;
    overflow: hidden;
}
.rect:before {top: 0px;}
.rect:after {
    bottom: 0px;
    -webkit-animation-direction: reverse;
    -moz-animation-direction: reverse;
    animation-direction: reverse;
}
@-webkit-keyframes translate {
    0% {-webkit-transform: translatex(0px);}
    100% {-webkit-transform: translateX(-43px);}
}
@-moz-keyframes translate {
    0% {-moz-transform: translatex(0px);}
    100% {-moz-transform: translateX(-43px);}
}
@keyframes translate {
    0% {transform: translatex(0px);}
    100% {transform: translateX(-43px);}
}
.left, .right {
    position: relative;
    height: 100px;
    width: 100px;
    border-radius: 50px;
    -webkit-animation: rotate 4.8s linear infinite;
    -moz-animation: rotate 4.8s linear infinite;
    animation: rotate 4.8s linear infinite;
}
.left {
    top: -110px; left: 0px;
}
.right {
    top: -210px; left: 344px;
}
.left:before, .left:after, .right:before, .right:after {
    height: 20px;
    width: 20px;
    content: '';
    position: absolute;
    background: gold;
}
.left:before, .right:before {
    box-shadow: 50px 50px 0 0 gold, -50px 50px 0 0 gold, 0 100px 0 0 gold;
    top: -10px;
    left: 40px;
}
.left:after, .right:after {
    transform: rotate(45deg);
    top: 5px;
    left: 76px;
    box-shadow: 0px 100px 0 0 gold, 50px 50px 0 0 gold, -50px 50px 0 0 gold;
}
@-webkit-keyframes rotate {
    0% {-webkit-transform: rotate(0deg);}
    100% {-webkit-transform: rotate(-360deg);}
}
@-moz-keyframes rotate {
    0% {-moz-transform: rotate(0deg);}
    100% {-moz-transform: rotate(-360deg);}
}
@keyframes rotate {
    0% {transform: rotate(0deg);}
    100% {transform: rotate(-360deg);}
}
.cover {
    height: 104px;
    width: 446px;
    border-radius: 50px;
    position: relative;
    background: rgba(255,255,255,1);
    top: -312px;
    left; -2px;
}
.gear, .gear2, .gear3 {
    height: 100px;
    width: 100px;
    background: transparent;
    box-shadow: inset 0 0 0px 35px dimgray, inset 0 0 0px 40px #444;
    border-radius: 50%;
    position: relative;
    -webkit-animation: rotate 4.8s linear infinite;
    -moz-animation: rotate 4.8s linear infinite;
    animation: rotate 4.8s linear infinite;
    -webkit-animation-delay: 0.3s;
    -moz-animation-delay: 0.3s;
    animation-delay: 0.3s;
}
.gear {top: -414px;}
.gear2 {top: -514px; left: 345px;}
.gear:before, .gear:after, .gear2:before, .gear2:after,  .gear3:before, .gear3:after {
    height: 20px;
    width: 20px;
    content: '';
    border-radius: 20%;
    position: absolute;
    background: dimgray;
}
.gear:before, .gear2:before, .gear3:before {
    box-shadow: 50px 50px 0 0 dimgray, -50px 50px 0 0 dimgray, 0 100px 0 0 dimgray;
    top: -10px; left: 40px;
}
.gear:after, .gear2:after, .gear3:after {
    transform: rotate(45deg);
    top: 5px; left: 76px;
    box-shadow: 0px 100px 0 0 dimgray, 50px 50px 0 0 dimgray, -50px 50px 0 0 dimgray;
}
.gear3 {
    -webkit-animation-direction: reverse;
    -moz-animation-direction: reverse;
    animation-direction: reverse;
    top: -504px;
    -webkit-animation-delay: 0s;
    -moz-animation-delay: 0s;
    animation-delay: 0s;
}_
_<div class="rect"></div>
<div class="left"></div>
<div class="right"></div>
<div class="cover"></div>
<div class="gear"></div>
<div class="gear2"></div>
<div class="gear3"></div>_

FIDDLE-ROUNDED TEETH


注:アニメーションの速度を上げるには、各要素のアニメーション時間を短くするだけです比例して

フィドル(高速)

18
The Pragmatick

以下は、CSSを使用してコグアニメーションを実現する別の方法です。このメソッドは、IE11、IE10、Firefox、Chrome、OperaおよびSafariでテストされています。

  • 内側の円を生成するためのインセットbox-shadowを持つ歯車/歯車の2つの円形要素。歯は、軸を中心に回転する子要素(通常+疑似)によって生成されます。
  • ベルトの湾曲部分は、ギアのスポークと同じ技術を使用して実現され、常に歯の間にあるように配置されます。
  • Linear-gradientを使用して上部と下部の境界が模倣される1つの長方形のコンテナー要素。この要素の背景(上下のグラデーションを除く)は単色であり、一種の欠点です。この単色は、両側の円形要素の半分を隠すために使用されます。
  • アニメーションは、(a)円形要素の両方を絶えず回転させる、および(b)グラデーション背景の背景位置を絶えず変更するという2つの方法で実現されます。
.chain {
    margin: 45px auto;
    height: 100px;
    width: 310px;
    position: relative;
    background: -webkit-linear-gradient(0deg, gold 50%, transparent 50%), -webkit-linear-gradient(0deg, gold 50%, transparent 50%), white;
    background: -moz-linear-gradient(90deg, gold 50%, transparent 50%), -moz-linear-gradient(90deg, gold 50%, transparent 50%), white;
    background: linear-gradient(90deg, gold 50%, transparent 50%), linear-gradient(90deg, gold 50%, transparent 50%), white;
    background-size: 41px 5px;
    background-repeat: repeat-x;
    background-position: 20px 0px, 20px 95px;
    -webkit-animation: bgPos 1s infinite linear;
    -moz-animation: bgPos 1s infinite linear;
    animation: bgPos 1s infinite linear;
}
.belt, .belt-after, .belt .spokes, .belt .spokes:before, .belt .spokes:after, .belt-after .spokes, .belt-after .spokes:before, .belt-after .spokes:after {
    position: absolute;
    content:'';
    height: 90px;
    width:15px;
    top: 0px;
    border-top: 5px solid gold;
    border-bottom: 5px solid gold;
    z-index: -1;
}
.belt, .belt-after {
    -webkit-animation: borderAnim 8s infinite linear;
    -moz-animation: borderAnim 8s infinite linear;
    animation: borderAnim 8s infinite linear;
}
.belt .spokes, .belt-after .spokes {
    top: -5px;
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    transform: rotate(45deg);
}
.belt .spokes:before, .belt-after .spokes:before {
    top: -5px;
    -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    transform: rotate(90deg);
}
.belt .spokes:after, .belt-after .spokes:after {
    top: -5px;
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    transform: rotate(45deg);
}
.belt {
    left: -16px;
}
.belt-after {
    right: -16px;
}
.gear {
    content:'';
    position: absolute;
    top: 5px;
    height: 90px;
    width: 90px;
    border-radius: 50%;
    -webkit-animation: borderAnim 8s infinite linear;
    -moz-animation: borderAnim 8s infinite linear;
    animation: borderAnim 8s infinite linear;
    box-shadow: inset 0px 0px 0px 30px gray;
    z-index: 4;
}
.gear:before, .gear .spokes, .gear .spokes:before, .gear .spokes:after {
    position: absolute;
    content:'';
    height: 88px;
    width:15px;
    top: -5px;
    border-top: 6px solid gray;
    border-bottom: 6px solid gray;
}
.gear:before {
    left: 37px;
    -webkit-transform: rotate(22.5deg);
    -moz-transform: rotate(22.5deg);
    transform: rotate(22.5deg);
}
.gear .spokes {
    left: 37px;
    -webkit-transform: rotate(67.5deg);
    -moz-transform: rotate(67.5deg);
    transform: rotate(67.5deg);
}
.gear .spokes:before {
    top: -6px;
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    transform: rotate(45deg);
}
.gear .spokes:after {
    -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    transform: rotate(90deg);
}
.chain .belt + .gear {
    left:-52px;
}
.chain .belt-after + .gear {
    right: -52.5px;
}
.gear-small {
    content:'';
    position: absolute;
    left: -92px;
    top: -20px;
    height: 50px;
    width: 50px;
    border-radius: 50%;
    -webkit-animation: borderAnim 6s infinite linear reverse;
    -moz-animation: borderAnim 6s infinite linear reverse;
    animation: borderAnim 6s infinite linear reverse;
    box-shadow: inset 0px 0px 0px 20px gray;
    z-index: -2;
}
.gear-small:before {
    position: absolute;
    content:'';
    left: 21px;
    top: -3px;
    height: 48px;
    width: 10px;
    border-top:4px solid gray;
    border-bottom: 4px solid gray;
}
.gear-small .spokes, .gear-small .spokes:before, .gear-small .spokes:after {
    position: absolute;
    content:'';
    left: 21px;
    top: -3px;
    height: 48px;
    width: 10px;
    border-top:4px solid gray;
    border-bottom: 4px solid gray;
}
.gear-small .spokes {
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    transform: rotate(45deg);
}
.gear-small .spokes:before {
    left: 0px;
    -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    transform: rotate(90deg);
}
.gear-small .spokes:after {
    left: 0px;
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    transform: rotate(45deg);
}
@-webkit-keyframes borderAnim {
    0% {
        -webkit-transform: rotate(360deg);
    }
    100% {
        -webkit-transform: rotate(0deg);
    }
}
@-moz-keyframes borderAnim {
    0% {
        -moz-transform: rotate(360deg);
    }
    100% {
        -moz-transform: rotate(0deg);
    }
}
@keyframes borderAnim {
    0% {
        transform: rotate(360deg);
    }
    100% {
        transform: rotate(0deg);
    }
}
@-webkit-keyframes bgPos {
    0% {
        background-position: 20px 0px, -20px 95px;
    }
    100% {
        background-position: -20px 0px, 20px 95px;
    }
}
@-moz-keyframes bgPos {
    0% {
        background-position: 20px 0px, -20px 95px;
    }
    100% {
        background-position: -20px 0px, 20px 95px;
    }
}
@keyframes bgPos {
    0% {
        background-position: 20px 0px, -20px 95px;
    }
    100% {
        background-position: -20px 0px, 20px 95px;
    }
}
<div class="chain">
    <div class="gear-small">
        <div class="spokes"></div>
    </div>
    <div class="belt">
        <div class="spokes"></div>
    </div>
    <div class="gear">
        <div class="spokes"></div>
    </div>
    <div class="belt-after">
        <div class="spokes"></div>
    </div>
    <div class="gear">
        <div class="spokes"></div>
    </div>
</div>

ボーナス:オン/オフスイッチ付きのアニメーション全体を次に示します:)チェーンハンドルをクリック(プル)して、アニメーションのオン/オフを切り替えます。

.container {
  position: relative;
}
.chain {
  margin: 45px 100px;
  height: 100px;
  width: 310px;
  position: relative;
  background: -webkit-linear-gradient(0deg, gold 50%, transparent 50%), -webkit-linear-gradient(0deg, gold 50%, transparent 50%), white;
  background: -moz-linear-gradient(90deg, gold 50%, transparent 50%), -moz-linear-gradient(90deg, gold 50%, transparent 50%), white;
  background: linear-gradient(90deg, gold 50%, transparent 50%), linear-gradient(90deg, gold 50%, transparent 50%), white;
  background-size: 41px 5px;
  background-repeat: repeat-x;
  background-position: 20px 0px, 20px 95px;
  -webkit-animation: bgPos 1s infinite linear;
  -moz-animation: bgPos 1s infinite linear;
  animation: bgPos 1s infinite linear;
}
.belt,
.belt-after,
.belt .spokes,
.belt .spokes:before,
.belt .spokes:after,
.belt-after .spokes,
.belt-after .spokes:before,
.belt-after .spokes:after {
  position: absolute;
  height: 90px;
  width: 15px;
  top: 0px;
  border-top: 5px solid gold;
  border-bottom: 5px solid gold;
  z-index: -1;
}
.belt,
.belt-after {
  -webkit-animation: borderAnim 8s infinite linear;
  -moz-animation: borderAnim 8s infinite linear;
  animation: borderAnim 8s infinite linear;
}
.belt .spokes,
.belt-after .spokes {
  top: -5px;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  transform: rotate(45deg);
}
.belt .spokes:before,
.belt .spokes:after,
.belt-after .spokes,
.belt-after .spokes:before,
.belt-after .spokes:after {
  content: '';
}
.belt .spokes:before,
.belt-after .spokes:before {
  top: -5px;
  -webkit-transform: rotate(90deg);
  -moz-transform: rotate(90deg);
  transform: rotate(90deg);
}
.belt .spokes:after,
.belt-after .spokes:after {
  top: -5px;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  transform: rotate(45deg);
}
.belt {
  left: -16px;
}
.belt-after {
  right: -16px;
}
.gear {
  position: absolute;
  top: 5px;
  height: 90px;
  width: 90px;
  border-radius: 100%;
  -webkit-animation: borderAnim 8s infinite linear;
  -moz-animation: borderAnim 8s infinite linear;
  animation: borderAnim 8s infinite linear;
  box-shadow: inset 0px 0px 0px 30px gray, inset 0px 0px 0px 40px white, inset 0px 0px 0px 50px tomato;
  z-index: 4;
}
.gear:before,
.gear .spokes,
.gear .spokes:before,
.gear .spokes:after {
  position: absolute;
  content: '';
  height: 88px;
  width: 15px;
  top: -5px;
  border-top: 6px solid gray;
  border-bottom: 6px solid gray;
}
.gear:before {
  left: 37px;
  -webkit-transform: rotate(22.5deg);
  -moz-transform: rotate(22.5deg);
  transform: rotate(22.5deg);
}
.gear .spokes {
  left: 37px;
  -webkit-transform: rotate(67.5deg);
  -moz-transform: rotate(67.5deg);
  transform: rotate(67.5deg);
}
.gear .spokes:before {
  top: -6px;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  transform: rotate(45deg);
}
.gear .spokes:after {
  -webkit-transform: rotate(90deg);
  -moz-transform: rotate(90deg);
  transform: rotate(90deg);
}
.chain .belt + .gear {
  left: -52px;
}
.chain .belt-after + .gear {
  right: -52.5px;
}
.gear-small {
  position: absolute;
  left: -91px;
  top: -20px;
  height: 50px;
  width: 50px;
  border-radius: 50%;
  -webkit-animation: borderAnim 8s 0.4s infinite linear;
  -moz-animation: borderAnim 6s infinite linear;
  animation: borderAnim 6s infinite linear;
  -webkit-animation-direction: reverse;
  -moz-animation-direction: reverse;
  animation-direction: reverse;
  box-shadow: inset 0px 0px 0px 20px gray;
  z-index: -2;
}
.gear-small:before {
  position: absolute;
  content: '';
  left: 21px;
  top: -3px;
  height: 48px;
  width: 10px;
  border-top: 4px solid gray;
  border-bottom: 4px solid gray;
}
.gear-small .spokes,
.gear-small .spokes:before,
.gear-small .spokes:after {
  position: absolute;
  content: '';
  left: 21px;
  top: -3px;
  height: 48px;
  width: 10px;
  border-top: 4px solid gray;
  border-bottom: 4px solid gray;
}
.gear-small .spokes {
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  transform: rotate(45deg);
}
.gear-small .spokes:before {
  left: 0px;
  -webkit-transform: rotate(90deg);
  -moz-transform: rotate(90deg);
  transform: rotate(90deg);
}
.gear-small .spokes:after {
  left: 0px;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  transform: rotate(45deg);
}
@-webkit-keyframes borderAnim {
  0% {
    -webkit-transform: rotate(360deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
  }
}
@-moz-keyframes borderAnim {
  0% {
    -moz-transform: rotate(360deg);
  }
  100% {
    -moz-transform: rotate(0deg);
  }
}
@keyframes borderAnim {
  0% {
    transform: rotate(360deg);
  }
  100% {
    transform: rotate(0deg);
  }
}
@-webkit-keyframes bgPos {
  0% {
    background-position: 20px 0px, -20px 95px;
  }
  100% {
    background-position: -20px 0px, 20px 95px;
  }
}
@-moz-keyframes bgPos {
  0% {
    background-position: 20px 0px, -20px 95px;
  }
  100% {
    background-position: -20px 0px, 20px 95px;
  }
}
@keyframes bgPos {
  0% {
    background-position: 20px 0px, -20px 95px;
  }
  100% {
    background-position: -20px 0px, 20px 95px;
  }
}
#pull-switch {
  display: none;
  /* no need to display checkbox */
}
#switch {
  position: absolute;
  left: 77px;
  top: 50px;
  border-right: 2px dotted tomato;
  height: 200px;
  width: 15px;
  -webkit-transition: height 0.5s;
  -moz-transition: height 0.5s;
  transition: height 0.5s;
  z-index: 10;
}
#handle {
  display: block;
  position: absolute;
  /* left: width of chain div (15px) + half of border (1px) - radius of handle (8px)*/
  left: 8px;
  bottom: 0%;
  background-color: tomato;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  cursor: pointer
}
#pull-switch:checked + #switch > #handle {
  background-color: seagreen;
}
#pull-switch:checked + #switch {
  height: 225px;
  border-color: seagreen;
}
#pull-switch ~ .chain .gear-small,
#pull-switch ~ .chain .belt,
#pull-switch ~ .chain .belt-after,
#pull-switch ~ .chain .gear,
#pull-switch ~ .chain {
  -webkit-animation-play-state: paused;
  -moz-animation-play-state: paused;
  animation-play-state: paused;
}
#pull-switch:checked ~ .chain .gear-small,
#pull-switch:checked ~ .chain .belt,
#pull-switch:checked ~ .chain .belt-after,
#pull-switch:checked ~ .chain .gear,
#pull-switch:checked ~ .chain {
  -webkit-animation-play-state: running;
  -moz-animation-play-state: running;
  animation-play-state: running;
}
#pull-switch:checked ~ .chain .belt + .gear,
#pull-switch:checked ~ .chain .belt-after + .gear {
  box-shadow: inset 0px 0px 0px 30px gray, inset 0px 0px 0px 40px white, inset 0px 0px 0px 50px seagreen;
}
<div class="container">
  <input type="checkbox" id="pull-switch" />
  <div id="switch">
    <label for="pull-switch" id="handle"></label>
  </div>
  <div class="chain">
    <div class="gear-small">
      <div class="spokes"></div>
    </div>
    <div class="belt">
      <div class="spokes"></div>
    </div>
    <div class="gear">
      <div class="spokes"></div>
    </div>
    <div class="belt-after">
      <div class="spokes"></div>
    </div>
    <div class="gear">
      <div class="spokes"></div>
    </div>
  </div>
</div>

元の回答:(破線の境界線のバグのためFirefoxで機能せず、ダッシュはIEで見苦しくなります)。

次の組み合わせを使用して、境界線回転アニメーションを実現できます。

  • 2つの円形要素(border-radius: 50%を使用)の両側に破線の境界線があり、境界線の曲線部分を形成します。
  • linear-gradientを使用して上部と下部の境界が模倣される1つの長方形のコンテナー要素。この要素の背景(上下のグラデーションを除く)は単色であり、一種の欠点です。この単色は、両側の円形要素の半分を隠すために使用されます。
  • アニメーションは、(a)円形要素の両方を絶えず回転させる、および(b)グラデーション背景のbackground-positionを絶えず変更する2つの方法で実現されます。
  • コグも円形の要素であり、スポークは破線の境界線で作成され、内側のソリッド部分はインセットbox-shadowを使用して生成されます。コグは、チェーンの境界が常にコグの境界の間にあるように回転します。
.chain {
  margin: 45px auto;
  height: 100px;
  width: 300px;
  position: relative;
  background: -webkit-linear-gradient(0deg, gold 50%, transparent 50%), -webkit-linear-gradient(0deg, gold 50%, transparent 50%), white;
  background: -moz-linear-gradient(90deg, gold 50%, transparent 50%), -moz-linear-gradient(90deg, gold 50%, transparent 50%), white;
  background: linear-gradient(90deg, gold 50%, transparent 50%), linear-gradient(90deg, gold 50%, transparent 50%), white;
  background-size: 30px 5px;
  background-repeat: repeat-x;
  background-position: 0px 0px, 5px 95px;
  -webkit-animation: bgPos 4s infinite linear;
  -moz-animation: bgPos 4s infinite linear;
  animation: bgPos 4s infinite linear;
}
.chain .before,
.chain .after {
  position: absolute;
  content: '';
  height: 90px;
  width: 90px;
  top: 0px;
  border-radius: 50%;
  border: 5px dashed gold;
  -webkit-animation: borderAnim 2s infinite linear;
  -moz-animation: borderAnim 2s infinite linear;
  animation: borderAnim 2s infinite linear;
  z-index: -2;
}
.chain .before {
  left: -45px;
}
.chain .after {
  right: -45px;
}
.chain .gear {
  content: '';
  position: absolute;
  top: 0px;
  height: 90px;
  width: 90px;
  border-radius: 50%;
  border: 5px dashed gray;
  -webkit-transform: rotate(16deg);
  -moz-transform: rotate(16deg);
  transform: rotate(16deg);
  -webkit-animation: gearAnim 2s infinite linear;
  -moz-animation: gearAnim 2s infinite linear;
  animation: gearAnim 2s infinite linear;
  box-shadow: inset 0px 0px 0px 30px gray;
  z-index: 4;
}
.chain .before + .gear {
  left: -45px;
}
.chain .after + .gear {
  right: -45px;
}
.gear-small {
  content: '';
  position: absolute;
  left: -95px;
  top: -23px;
  height: 60px;
  width: 60px;
  border-radius: 50%;
  border: 3px dashed gray;
  -webkit-transform: rotate(16deg);
  -moz-transform: rotate(16deg);
  transform: rotate(16deg);
  -webkit-animation: gearAnim 6s infinite linear reverse;
  -moz-animation: gearAnim 6s infinite linear reverse;
  animation: gearAnim 6s infinite linear reverse;
  box-shadow: inset 0px 0px 0px 20px gray;
  z-index: -2;
}
@-webkit-keyframes borderAnim {
  0% {
    -webkit-transform: rotate(360deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
  }
}
@-moz-keyframes borderAnim {
  0% {
    -moz-transform: rotate(360deg);
  }
  100% {
    -moz-transform: rotate(0deg);
  }
}
@keyframes borderAnim {
  0% {
    transform: rotate(360deg);
  }
  100% {
    transform: rotate(0deg);
  }
}
@-webkit-keyframes bgPos {
  0% {
    background-position: 610px 0px, 0px 95px;
  }
  100% {
    background-position: 0px 0px, 600px 95px;
  }
}
@-moz-keyframes bgPos {
  0% {
    background-position: 610px 0px, 0px 95px;
  }
  100% {
    background-position: 0px 0px, 600px 95px;
  }
}
@keyframes bgPos {
  0% {
    background-position: 610px 0px, 0px 95px;
  }
  100% {
    background-position: 0px 0px, 600px 95px;
  }
}
@-webkit-keyframes gearAnim {
  0% {
    -webkit-transform: rotate(376deg);
  }
  100% {
    -webkit-transform: rotate(16deg);
  }
}
@-moz-keyframes gearrAnim {
  0% {
    -moz-transform: rotate(376deg);
  }
  100% {
    -moz-transform: rotate(16deg);
  }
}
@keyframes gearAnim {
  0% {
    transform: rotate(376deg);
  }
  100% {
    transform: rotate(16deg);
  }
}
<div class="chain">
  <div class="gear-small"></div>
  <div class="before"></div>
  <div class="gear"></div>
  <div class="after"></div>
  <div class="gear"></div>
</div>

最後に大事なことを言い忘れましたが、特定のポイントを超えるとCSSを使用したアニメーションは非常に面倒になるため、SVGアプローチの使用をお勧めします。

15
Harry

Divの境界線を微調整してcogの所定の位置に収まるのではなく、cogをより適切に編集してみてください。 CSSよりもグラフィックスの操作が簡単です。

そこから、チェーンアニメーションを3つまたは4つの部分に分割して、より堅牢にすることもできます。

次に、コグとチェーンの速度を調整して一致させ、チェーンの半分を非表示にし、上下の境界線のみでdivに追加し、反対側で同じですが反対のことを行うことができます。 (クリッピング、位置、およびZインデックスを使用)。

このようなもの:

xhtml

少なくとも理論的には、それが私のアプローチになります(このワークフローの代わりにJSを使用することは言うまでもありません)。

4
Drops

Canvasを使用する

図形(歯車とチェーン)と行進するアリのアニメーション効果(破線の境界線)も、キャンバスの描画を使用して実現できます。 Canvasのブラウザサポートは かなり良い です。

Canvasには、ラスタベースであるという欠点があります(形状ベースのSVGとは対照的です)が、キャンバスがあまり大きくスケーリングされない限り、大きな問題ではありません。 Canvasは、多数のオブジェクトとリアルタイムアニメーションを処理する場合に優れていると予想されます。 ここ は、CanvasまたはSVGをいつ使用するかに関するMSDNの興味深い記事です。


形状の構築

以下は、このアニメーションに含まれる重要なパーツ/形状です。

  • 左コグ
  • 右コグ
  • トップコグ

Chain:チェーンは、両端で半円で結ばれた(lineToコマンドを使用して)2本の水平線を描画することで作成されます(描画) arcコマンドを使用)。破線の境界線効果は、ストロークにsetLineDashメソッドを使用することで実現されます。 setLineDashメソッドは2つのパラメーターを取ります。最初のパラメーターはダッシュの長さを表し、2番目のパラメーターはダッシュ間のギャップを表します。

以下のスニペットは、チェーンを作成するために必要な最小限のコードを示しています。

window.onload = function() {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  var chain = {
    offset: 0,
    Paint: function() {
      ctx.beginPath();
      ctx.moveTo(75, 50);
      ctx.lineTo(533, 50);
      ctx.arc(533, 100, 50, (Math.PI * 1.5), (Math.PI * 0.5), false);
      ctx.lineTo(75, 150);
      ctx.arc(75, 100, 50, (Math.PI * 0.5), (Math.PI * 1.5), false);
      ctx.lineWidth = 5;
      ctx.fillStyle = 'transparent';
      ctx.setLineDash([12, 14.16]);
      ctx.lineDashOffset = this.offset;
      ctx.fill();
      ctx.stroke();
    }
  };

  chain.Paint();
}
/* CSS needed only for demo */

body {
  background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
canvas {
  margin: 50px auto;
}
<canvas id='canvas' width='650' height='300'></canvas>

コグ:3つのコグ(左、右、上)はすべて同じコマンドを使用して実現され、唯一の違いは画面上の位置(および半径一番上)。

歯車のスポークまたは歯はarcコマンドを使用して作成され(チェーンの半円に対して行われます)、同じ半径を使用します。 lineDashoffsetは、チェーンのダッシュ間に残された正確なスペースを占めるように調整されます。

歯車の本体は2つの円で構成されており、外側の円は内側よりも大きな半径を持っています。 evenodd fillパラメーターを使用して、外側の円のみに背景色(この例ではtan)を設定し、内側の円は透明のままにします。

以下のスニペットは、歯車の作成に必要な最小限のコードを示しています。

window.onload = function() {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  var cog = {
    Paint: function(x, y, r, offset) {
      ctx.beginPath();
      ctx.arc(x, y, r, 0, Math.PI * 2, true);
      ctx.closePath();
      ctx.lineWidth = 5;
      ctx.setLineDash([12, 14.16]);
      ctx.lineDashOffset = offset;
      ctx.strokeStyle = 'tan';
      ctx.stroke();
      ctx.beginPath();
      ctx.arc(x, y, (r - 2), 0, Math.PI * 2, true);
      ctx.arc(x, y, (r / 2.5), 0, Math.PI * 2, true);
      ctx.closePath();
      ctx.fillStyle = 'tan';
      ctx.fill('evenodd');
    }
  };

  function Paint() {
    var cog_radius = 50;
    var cog_t_x = 30,
      cog_t_y = 40,
      cog_t_offset = 20.5,
      cog_l_x = 75,
      cog_l_y = 100,
      cog_l_offset = 24.25,
      cog_r_x = 533,
      cog_r_offset = 11.25;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.save();
    cog.Paint(cog_t_x, cog_t_y, (cog_radius / 2), cog_t_offset);
    ctx.restore();
    ctx.save();
    cog.Paint(cog_l_x, cog_l_y, cog_radius, cog_l_offset);
    ctx.restore();
    ctx.save();
    cog.Paint(cog_r_x, cog_l_y, cog_radius, cog_r_offset);
    ctx.restore();
  }
  Paint();

}
/* CSS needed only for demo */

body {
  background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
canvas {
  margin: 50px auto;
}
<canvas id='canvas' width='650' height='300'></canvas>

アニメーション

アニメーションは、アニメーションの各フレームのストロークのlineDashOffsetをシフトすることにより実現されます。アニメーション自体は window.requestAnimationFrame 一定の間隔でPaint関数(引数として渡される)を呼び出すメソッド。コールバックの速度は、通常1秒あたり60回です(MDNを引用)。キャンバスの再描画のたびにオフセットをシフトすると、アニメーション化されたように見えます。

cancelAnimationFrame メソッドを呼び出すことで、いつでもアニメーションを停止できます。これは、ユーザーの操作(クリック、ホバーなど)に基づいて、またはタイムアウトに基づいて実行できます。

window.onload = function() {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  var anim, onState = false,
    counter = 0;
  var chain = {
    offset: 0,
    Paint: function() {
      ctx.beginPath();
      ctx.moveTo(75, 50);
      ctx.lineTo(533, 50);
      ctx.arc(533, 100, 50, (Math.PI * 1.5), (Math.PI * 0.5), false);
      ctx.lineTo(75, 150);
      ctx.arc(75, 100, 50, (Math.PI * 0.5), (Math.PI * 1.5), false);
      ctx.lineWidth = 5;
      ctx.fillStyle = 'transparent';
      ctx.setLineDash([12, 14.16]);
      ctx.lineDashOffset = this.offset;
      ctx.fill();
      ctx.stroke();
    }
  };

  function Paint(type) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    chain.offset += (6.54 / 10);
    ctx.save();
    chain.Paint();
    ctx.restore();
    if (type) {
      anim = window.requestAnimationFrame(function() {
        Paint(type);
      })
    }
  }
  Paint(true);
}
/* CSS needed only for demo */

body {
  background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
canvas {
  margin: 50px auto;
}
<canvas id='canvas' width='650' height='300'></canvas>

完全な画像

すべてのパーツをまとめると、以下のスニペットは、アニメーションとともにチェーンとコグの全体像を提供します。

window.onload = function() {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  var anim, onState = false,
    counter = 0;
  var cog_radius = 50;
  var cog_t_x = 30,
    cog_t_y = 40,
    cog_t_offset = 20.5,
    cog_l_x = 75,
    cog_l_y = 100,
    cog_l_offset = 24.25,
    cog_r_x = 533,
    cog_r_offset = 11.25;
  var chain = {
    offset: 0,
    Paint: function() {
      ctx.beginPath();
      ctx.moveTo(75, 50);
      ctx.lineTo(533, 50);
      ctx.arc(533, 100, 50, (Math.PI * 1.5), (Math.PI * 0.5), false);
      ctx.lineTo(75, 150);
      ctx.arc(75, 100, 50, (Math.PI * 0.5), (Math.PI * 1.5), false);
      ctx.lineWidth = 5;
      ctx.fillStyle = 'transparent';
      ctx.setLineDash([12, 14.16]);
      ctx.lineDashOffset = this.offset;
      ctx.fill();
      ctx.stroke();
    }
  };
  var cog = {
    Paint: function(x, y, r, offset) {
      ctx.beginPath();
      ctx.arc(x, y, r, 0, Math.PI * 2, true);
      ctx.closePath();
      ctx.lineWidth = 5;
      ctx.setLineDash([12, 14.16]);
      ctx.lineDashOffset = offset;
      ctx.strokeStyle = 'tan';
      ctx.stroke();
      ctx.beginPath();
      ctx.arc(x, y, (r - 2), 0, Math.PI * 2, true);
      ctx.arc(x, y, (r / 2.5), 0, Math.PI * 2, true);
      ctx.closePath();
      ctx.fillStyle = 'tan';
      ctx.fill('evenodd');
    }
  };

  function Paint(type) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    chain.offset += (6.54 / 10);
    cog_l_offset -= (6.54 / 10);
    cog_r_offset -= (6.54 / 10);
    cog_t_offset += (6.54 / 10);
    ctx.save();
    cog.Paint(cog_t_x, cog_t_y, (cog_radius / 2), cog_t_offset);
    ctx.restore();
    ctx.save();
    chain.Paint();
    ctx.restore();
    ctx.save();
    cog.Paint(cog_l_x, cog_l_y, cog_radius, cog_l_offset);
    ctx.restore();
    ctx.save();
    cog.Paint(cog_r_x, cog_l_y, cog_radius, cog_r_offset);
    ctx.restore();
    if (type) {
      anim = window.requestAnimationFrame(function() {
        Paint(type);
      })
    }
  }
  Paint(true);
}
/* CSS needed only for demo */

body {
  background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
canvas {
  margin: 50px auto;
}
<canvas id='canvas' width='650' height='300'></canvas>

ユーザーインタラクション

前述のように、ユーザーインタラクションはイベントリスナー(addEventListener)を使用して追加することもできます。キャンバスの特定の形状またはセクションでユーザーアクションによってアクションをトリガーする必要がある場合、pointInPathメソッドを使用して、ポイントがキャンバスの必要なセクション内にあるかどうかを確認できます。

ここ は、これらのユーザーインタラクション(およびその他の追加機能)も追加されたCodePenデモへのリンクです。

注:ユーザーインタラクションの追加方法などの説明は、この特定の回答の範囲を超えています。しかし、助けが必要な場合は this chat room で見つけることができます。

3
Harry