css css3 svg css-shapes svg-animate

css - Barra de progreso SVG



svg sprite (4)

Tengo un requisito donde necesito cargar archivos js dinámicamente y mostrar el progreso de la carga de archivos a través de un icono SVG. El icono SVG actuará como barra de progreso donde se llena con un color de abajo hacia arriba, de forma lineal.

Aquí está el codepen

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844"> <path fill="transparent" stroke="black" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> </svg>

Estoy planeando hacer que este icono sea independiente de modo que solo pase el valor de porcentaje dinámicamente.

De alguna manera, puedo hacer la animación pero no puedo mantener el borde o el contorno del svg. Aquí está el code .

#progressMove { transition: .3s y; } #progressMove:hover { y: 60%; }

<svg id="kenseoProgress" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844"> <defs> <mask id="bubbleKenseo"> <path fill="red" stroke="black" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> </mask> </defs> <g x="0" y="0" width="79.36px" height="93.844px" mask="url(#bubbleKenseo)" height="100"> <rect id="progressMove" x="0" y="0%" width="100%" height="100%" fill="blue" stroke="black" /> </g> </svg>

Entonces, los problemas que tengo son:

  • No se puede mantener la frontera con el SVG
  • Cualquiera que sea el color que agregué, tendrá un tipo de opacidad que no puedo eliminar.
  • Edición : compatibilidad del navegador: IE11 +, chrome, safari y firefox

PD: no quiero usar animaciones SMIL.


SOLUCION CROMO / SAFARI

Usando la transform propiedad CSS y counter-increment puede lograr el incremento de relleno y número.

jsFiddle

FRAGMENTO DE CÓDIGO

for (var i = 0; i < 100; i++) { setTimeout(function() { $(".progress-container p").append("<span>"); }, i * 20); }

pattern #progressMove { transform: translateY(100%); color: purple; animation: progressBar 2s steps(100, end) forwards; } @keyframes progressBar { to { transform: translateY(0); } } .progress-container { margin: 0; display: inline-block; position: relative; counter-reset: progress; } .progress-container figcaption { position: absolute; top: 40%; left: 50%; transform: translate(-40%, -50%); } .progress-container p { margin: 0; font-weight: bold; } .progress-container span { counter-increment: progress; } .progress-container p::after { content: counter(progress)"%"; }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <figure class="progress-container"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844"> <pattern id="progress" x="0" y="0" width="79.36" height="93.844" patternUnits="userSpaceOnUse"> <rect id="progressMove" x="0" y="0" width="100%" height="100%" stroke="none" fill="currentColor" /> </pattern> <path fill="url(#progress)" stroke="#000" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> </svg> <figcaption> <p> </p> </figcaption> </figure>

Nota:

Se actualizará si puedo ofrecer una mejor solución para cubrir el soporte del navegador.

EDITAR:

En Persijn respuesta de Persijn , también deberá cambiar el color del fondo al de su padre.

El componente completo sería el elemento de figure , lamentablemente el símbolo en la hoja de cálculo solo se usará para proporcionar la ruta y el fondo.

Nota: jQuery eliminado en esta versión.

jsFiddle

for (var i = 0; i < 100; i++) { setTimeout(function() { var progressCounter = document.querySelector(".progress__counter"), number = document.createElement("span"); progressCounter.appendChild(number); }, i * 20); }

#spritesheet { display: none; } .icon { display: inline-block; width: 1em; height: 1em; } .icon-bubble { font-size: 7em; color: white; } .progress-container { margin: 0; display: inline-block; position: relative; counter-reset: progress; overflow: hidden; line-height: 0; } .progress__inner { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; } .progress__fill { background-color: purple; height: 100%; transform: translateY(100%); animation: progressFill 2s steps(100, end) forwards; } @keyframes progressFill { to { transform: translateY(0); } } .progress__counter { position: absolute; top: 40%; left: 50%; transform: translate(-40%, -50%); margin: 0; font-weight: bold; } .progress__counter span { counter-increment: progress; } .progress__counter::after { content: counter(progress)"%"; }

<figure class="progress-container"> <svg class="icon icon-bubble"> <use xlink:href="#icon-bubble"></use> </svg> <figcaption class="progress__inner"> <div class="progress__fill"></div> <p class="progress__counter"></p> </figcaption> </figure> <svg id="spritesheet"> <symbol id="icon-bubble" viewBox="0 0 79.36 93.844"> <title>Loading Bubble</title> <path id="bubble-cover" fill="currentColor" stroke="#000" d="M-10,-10 100,-10 100,100 -10,100 -10,-10 50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> </symbol> </svg>

Pruebas:

  • Cromo 53
  • IE10
  • Borde
  • FireFox 47
  • IOS 10 Safari

PATIO DE RECREO

jsFiddle

for (var i = 0; i < 100; i++) { setTimeout(function() { var progressCounter = document.querySelector(".progress__counter"), number = document.createElement("span"); progressCounter.appendChild(number); }, i * 20); }

#spritesheet { display: none; } .icon { display: inline-block; width: 1em; height: 1em; } .icon-bubble { font-size: 7em; color: white; } .progress-container { margin: 0; display: inline-block; position: relative; counter-reset: progress; overflow: hidden; line-height: 0; } .progress__inner { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; } .progress__fill { background-color: purple; height: 100%; transform: translateY(100%); animation: progressFill 2s steps(100, end) forwards, progressFillColor 100ms linear 2s forwards; position: relative; } @keyframes progressFill { to { transform: translateY(0); } } @keyframes progressFillColor { to { background-color: green; } } .progress__counter { position: absolute; top: 40%; transform: translateY(-40%); text-align: center; width: 100%; margin: 0; font-weight: bold; animation: progressCounter 100ms linear 1s forwards; } .progress__counter span { counter-increment: progress; } .progress__counter::after { content: counter(progress)"%"; animation: progressCounterCompleted 1s linear 2s forwards; } @keyframes progressCounter { to { color: white; } } /* Chrome Only*/ @keyframes progressCounterCompleted { 33% { content: "File(s)"; } 66% { content: "Uploaded"; } 100% { content: "Successfully!"; } }

<figure class="progress-container"> <svg class="icon icon-bubble"> <use xlink:href="#icon-bubble"></use> </svg> <figcaption class="progress__inner"> <div class="progress__fill"></div> <p class="progress__counter"></p> </figcaption> </figure> <svg id="spritesheet"> <symbol id="icon-bubble" viewBox="0 0 79.36 93.844"> <title>Loading Bubble</title> <path id="bubble-cover" fill="currentColor" stroke="#000" d="M-10,-10 100,-10 100,100 -10,100 -10,-10 50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> </symbol> </svg>


En primer lugar, desea utilizar clip-path o establecer el relleno de la mask en blanco para una opacidad del 100%: la mask se utiliza como un canal alfa en escala de grises y el color de relleno rojo provoca el cambio de opacidad.

En cuanto al trazo, desea agregarlo como un elemento separado que no se vea afectado por el recorte. (Probablemente pueda reutilizar la ruta con las defs y el use , simplemente la defs y defs aquí)

#progressMove { transition: .3s y; } #progressMove:hover { y: 60%; }

<svg id="kenseoProgress" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844"> <defs> <clipPath id="bubbleKenseo"> <path d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> </clipPath> </defs> <path stroke="black" stroke-width="1" fill="transparent" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> <g x="0" y="0" width="79.36px" height="93.844px" clip-path="url(#bubbleKenseo)" height="100"> <rect id="progressMove" x="0" y="0%" width="100%" height="100%" fill="blue" stroke="black" /> </g> </svg>


SVG con patrón y transición y:

svg:hover pattern #fillshape { y: 0%; } pattern #fillshape { transition: y 1s; y: 100%; }

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844"> <pattern id="pattern1" x="0" y="0" width="79.36" height="93.844" patternUnits="userSpaceOnUse" > <rect id="fillshape" x="0" y="0" width="100%" height="200%" stroke="none" fill="purple" /> </pattern> <path fill="url(#pattern1)" stroke="black" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> </svg>

Ahora esto no funciona en Firefox o Edge . No reconoce xey como propiedades CSS ...

Aquí hay una solución que usa un div detrás de la forma svg. La desventaja de esta solución es que la forma svg obtiene un fondo, por ejemplo. Si solo desea la forma, deberá hacer coincidir el color de fondo de la forma con el del fondo de la página.

svg { position: relative; } .spesial { width: 90px; height: 0px; display: inline-block; background-color: purple; margin-left: -100px; transition: height 1s; } svg:hover + .spesial { height: 100px; }

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100" height="100" viewBox="0 0 75 90"> <path stroke="black" fill="gray" d="M-10,-10 100,-10 100,100 -10,100 -10,-10 50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> </svg> <div class="spesial"> </div>


var prObject = document.getElementById("prObject"), prDom = document.getElementById("progressMove"), prValue = 0; prObject.onmouseenter = function() { prDom.setAttribute(''class'', ''prHover'') }; prObject.onmouseleave = function() { prDom.removeAttribute(''class'') }; /*prDom.setAttributeNS(null, ''y'', ''0'');*/ var cTimer = setInterval(function() { prValue += 20.6; prDom.style.transform = "translateY(" + [100 - Math.min(prValue, 100)] + "%)"; if (prValue >= 100) { clearInterval(cTimer); } }, 450);

#progressMove { transition: transform 0.20s linear; } #progressMove.prHover { transform: translateY(40%) !important; }

<!DOCTYPE html> <html> <head> <title></title> </head> <body> <svg id="kenseoProgress" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844"> <defs> <path id="mypath" fill="white" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" /> <mask id="bubbleKenseo"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#mypath"></use> </mask> </defs> <g x="0" y="0" width="79.36px" height="93.844px" mask="url(#bubbleKenseo)" height="100" stroke-width="0"> <rect id="progressMove" x="0" y="0" width="100%" height="100%" fill="blue" stroke="black" style="transform: translateY(100%);" /> </g> <g id="prObject" x="0" y="0" width="79.36px" height="93.844px" height="100" fill-opacity="0" stroke="black" stroke-width="0.5px"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#mypath"></use> </g> </svg> </body> </html>