vienen van tienen paseo original marchas marcha letra las instrumental infantiles hormigas fuerza canciones cancion css css3 svg css-animations css-shapes

css - van - Cómo hacer una animación de rotación de bordes discontinua suave como ''hormigas marchando''



marcha de las hormigas original letra (6)

Estoy trabajando en una animación CSS que usa ''engranajes y cadenas'', pero no puedo crear una secuencia de rotación de bordes ''suave''.

Puedes ver en este fiddle cómo (actualmente) estoy usando un pseudo elemento para generar un efecto de ''rotación''. Esto se hace "alternando" entre un borde punteado de color blanco y dorado, haciendo que parezca que el "borde está girando".

Lo que tengo

#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>

Entonces, en la sección inferior del fragmento, puede ver cómo he generado el ''efecto de cadena giratoria'' mediante el uso de fotogramas clave.

Lo que me gustaría

Mi deseo general sería generar algo como:

Piense en una sección transversal de una cinta transportadora, y cómo los ''engranajes en el extremo conducen la correa''. Estoy tratando de reproducir eso. (es decir, los pedacitos de oro del borde punteado deben estar dentro de los valles del engranaje, y ''ser jalado'' por él)

#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>

pero con los guiones de oro para caber dentro de los canales del engranaje, además de tener un ancho del 80% de la pantalla (si tiene sentido).

Al final, me gustaría generar algo como esta imagen retrata:

¿Ves cómo quiero que la cadena ''gire''?

Mis problemas actuales

  • Como la animación se "piratea" mediante el uso de un pseudo elemento, me resulta bastante difícil sincronizar la rotación de esta "cadena".
  • Todavía estoy aprendiendo animación de fotogramas clave, así que estoy seguro de que no es el mejor método para esto
  • De nuevo, svg es un nuevo concepto para mí, así que ten cuidado con mi renuencia a usarlo (de ahí por qué estoy usando CSS para la ''cadena'')
  • Al final, quiero ''hacer que parezca'' que el engranaje está girando la cadena, pero ahora parecen completamente (y mal hechas) animaciones de elementos separados

Using Canvas

The shapes (cog and chain) and the marching ants animation effect (dashed border) can also be achieved by using a Canvas drawing. The browser support for Canvas is quite good .

While Canvas has the disadvantage of being raster based (as opposed to SVG, which is shape based), it is not a big problem as long as the canvas is not scaled too much. Canvas is expected to be better when handling a large number of objects and real-time animations. Here is an interesting article from the MSDN on when to use Canvas or SVG.

Construction of Shapes

The following are the key parts/shapes involved in this animation:

  • Cadena
  • Left Cog
  • Right Cog
  • Top Cog

Chain : The chain is created by drawing two horizontal lines (using the lineTo commands) that are connected at either end by semicircles (drawn using the arc command). The dashed border effect is achieved by using setLineDash method for the stroke. setLineDash method takes two parameters where the first represents the length of the dash and the second represents the gap between dashes.

Below snippet shows the minimal code required to create the chain:

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>

Cogs : All the three cogs (left, right and top) are achieved using the same commands and the only difference is their positioning on screen (and radius for the top one).

The spokes or teeth of the cogs are created by using the arc command (as done for the semicircles of the chain), and use the same radius. Their lineDashoffset is adjusted such that they occupy the exact space left between the dashes of the chain.

The body of the cogs are made up of two circles with the outer one having a bigger radius than the inner. The evenodd fill parameter is used to set the background color ( tan in this example) only on the outer circle and leaving the inner one transparent.

Below snippet shows the minimal code required to create the cogs:

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>

Animación

The animation is achieved by shifting the lineDashOffset of the strokes in each frame of the animation. The animation itself is triggered using the window.requestAnimationFrame method which calls the paint function (passed as an argument) at regular intervals. The rate of callback is generally 60 times per second (quoting MDN). Shifting the offset during every repaint of the canvas gives the appearance of it being animated.

The animation can be stopped at any point of time by calling the cancelAnimationFrame method. This can be done either based on some user interaction (like click, hover etc), or based on a time-out.

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>

Complete Picture

Putting all the parts together, the below snippet provides the complete picture of the chain and cogs along with the animation:

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>

La interacción del usuario

As mentioned earlier, user interaction can also be added using event listeners ( addEventListener ). If the action needs to be triggered by user action on a specific shape or section of the canvas then the pointInPath method can be used to verify if the point is within the required section of the canvas.

Here is the link to a CodePen demo which has these user interactions (and some other extra stuff) also added.

Note: Explanation on how to add user interactions etc is beyond the scope of this particular answer. However, if you need any help you can find me in this chat room .


Cog y cadena de animación:

Redefiní totalmente el código ( CSS y HTML ), ahora es:

  • más corto (especialmente el css)
  • más simple
  • más realista: corrigió el problema de sincronización entre la cadena y los engranajes y agregó una rueda faltante a la derecha porque su cadena parecía flotar en el aire:

DEMO

El enfoque es el mismo, animando el ángulo de rotación para los dientes y dash-offset del trazo para la ruta de la cadena. Ajusté el tiempo entre ambas animaciones para que pareciera que los engranajes están tirando de la cadena.

Soporte del navegador:

Como IE no es compatible con el elemento svg animado, también hice esta versión de la animación con la biblioteca snap.svg que también es compatible con IE9 y más (probado en IE9 con crossbrowsertesting ).

DEMO con soporte de 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>

Respuesta original:

Puede usar otra ruta svg discontinua y animar la propiedad de desplazamiento de guión con una animación de fotograma clave.

Esto puede y debe simplificarse / ajustarse para un uso en el "mundo real":

  • todos los elementos pueden estar contenidos en una etiqueta <svg> (esto lo haría más simple y ambos cogs + cadena podrían redimensionarse)
  • La sincronización entre la cadena y el engranaje no es perfecta y la velocidad / tamaño de la cadena necesita ser ajustada.

#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>


¿Qué hay de este enfoque? Estoy usando SVG tanto para los engranajes como para el transportador. Los engranajes giran según su ejemplo, pero estoy usando stroke-dasharray y animando stroke-dash-offset para mover la cinta transportadora.

Tomó un poco de toquetear para obtener la longitud del transportador y el tiempo del tablero correctamente, lo cual necesitaría modificar nuevamente si cambia el tamaño del engranaje o la longitud del transportador.

#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>


Aquí hay un método diferente sobre cómo lograr la animación de engranaje usando CSS. Este método ha sido probado en IE11, IE10, Firefox, Chrome, Opera y Safari.

  • Dos elementos circulares para engranajes / engranajes con recuadro box-shadow para producir el círculo interno. Los dientes son producidos por elementos secundarios (normal + pseudo) que giran alrededor del eje.
  • La parte curva de la correa se logra utilizando la misma técnica que los radios del engranaje y se colocan de manera que siempre estén entre los dientes.
  • Un elemento contenedor rectangular cuyos bordes superior e inferior se imitan usando gradiente lineal. El fondo de este elemento (que no sea el degradado en la parte superior e inferior) es un color sólido que es una especie de inconveniente. Este color sólido se utiliza para ocultar la mitad del elemento circular en cualquier lado.
  • La animación se logra de dos maneras (a) girando constantemente tanto los elementos circulares como (b) cambiando constantemente la posición de fondo de los fondos degradados.

.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>

Bonificación: aquí está toda la animación con un interruptor de encendido / apagado :) Haga clic (tire) del asa de la cadena para activar o desactivar la animación.

.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>

Original Answer: (Doesn''t work on Firefox due to dashed border bug and dashes are more closer in IE making it look ugly).

You could achieve the border rotation animation by using a combination of the following:

  • Two circular elements (using border-radius: 50% ) with dashed border on either side to form the curved part of the border.
  • One rectangular container element whose top and bottom borders are mimicked using linear-gradient . The background of this element (other than the gradient on top and bottom) is a solid color which is sort of a drawback. This solid color is used to hide half of the circular element on either side.
  • The animation is achieved in two ways (a) constantly rotating both the circular elements and (b) constantly changing the background-position of the gradient backgrounds.
  • The cogs are also circular elements where the spokes are made with dashed borders and the solid inner part is generated using an inset box-shadow . The cog is rotated in such a way that the chain''s border is always in between the cog''s border.

.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>

Last but not least, I would still recommend using the SVG approach for this because beyond a certain point such animations with CSS would become very messy :)


Nota: he rehecho toda la animación en box-shadow, porque el uso de bordes discontinuos no tiene salida consistente en todos los navegadores.

Trabajando

.. y funciona en todos los navegadores.
FF 5+, GC 4+, IE9 +, Safari 4+, Opera 12.1+

Puedes probar esto usando box-shadow:

  • Para hacer que los engranajes tengan dientes, use la sombra de caja con radio de propagación negativo. El tamaño de mi equipo era de 50px por ejemplo, así que para redondear mi box-shadow con d=8px , utilicé -46px como radio expandido.

  • Coloqué los dientes usando coordenadas geográficas, y solo utilicé 8 dientes para simplificar.

  • Ahora, para el transportador recto, necesitamos saber la distancia entre los dientes. Lo conseguimos por lo siguiente:

  • 2*pi*(gear radius) / no. of teeth 2*pi*(gear radius) / no. of teeth = (pi * r) / 4
    Mina = (55 * 3.1415) / 4 = 43 (aprox.)
    Tomé el radio como 55 porque los dientes tienen 4px de radio y están a 1px de la circunferencia del engranaje.

  • Para alinear los transportadores rectos superior e inferior, necesitan ser traducidos por cualquier múltiplo de su distancia. Para mi equipo, los traduzco por 43px.

El andamio

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>

Versión definitiva

... con engranajes. ¡La cadena actualmente está punteada !

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>

Versión final (diente redondo redondeado)

.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 - DIENTES REDONDEADOS

NOTA: Para aumentar la velocidad de la animación, simplemente tiene que disminuir la duración de la animación de cada elemento proporcionalmente .

Fiddle (rápido)


You could try and edit cog so it fits better instead of tweaking div border to fall into place on cog. Its easier to manipulate graphics than css.

And from there maybe to split chain animation in three or four parts to make it more robust.

Then you could tweak speeds of cog and chain to match, hide a half of chain, add onto it div only with top and bottom border and do the same but opposite on other end. (using cliping, position and z-index).

Algo como esto:

In theory at least, that would be my approach (not to mention that I would use JS instead of this workflow).