Advertisement
  1. Web Design
  2. jQuery

Como Crear una Página con un Indicador de Progreso con jQuery y SVG

Scroll to top
Read Time: 10 min

Spanish (Español) translation by Rodney Martinez (you can also view the original English article)

Hoy veremos algunas técnicas que podemos usar para mostrar una barra de desplazamiento para usuarios que están viendo la página. Esta técnica está siendo utilizada en un creciente número de sitios, y por buenas razones, está proporciona un entendimiento contextual de inversión necesaria para consumir una página en particular. Mientras los usuarios se desplazan, a ellos se les presenta una sensación de progreso en diferentes formatos.

Como se aprecia en ia.net

Hoy, abordaremos dos técnicas específicas que usted puede emplear para mostrar la barra de progreso y dejarlo con un conjunto de herramientas para crear las suyas. ¡Empecemos!

Configurando el Documento

Primero, vamos a configurar un boceto de un documento que actuara como nuestra página de publicación. Usaremos normalize.css y jQuery así como también Google gont. Su archivo HTML vacío debería lucir así:

1
<!doctype html>
2
<html>
3
    <head>
4
        <title>Progress Indicator Animation</title>
5
        <link rel="stylesheet" href="css/normalize.css">
6
        <link rel="stylesheet" href="css/style.css">
7
    </head>
8
    <body>
9
        <!-- fake post content goes here -->
10
        <script src="js/jquery.min.js"></script>
11
        <script src="js/script.js"></script>
12
    </body>
13
</html>

A continuación, vamos a añadir nuestro contenido falso:

1
<main>
2
    <article>
3
        <header>
4
            <h1>
5
                <div class="container">
6
                    How Should We Show Progress While Scrolling a Post?
7
                </div>
8
            </h1>
9
        </header>
10
        <div class="article-content">
11
                <h2 class="lead-in">
12
                    <div class="container">
13
                        Lorem ipsum dolor sit amet, consectetur adipisicing elit.
14
                    </div>
15
                </h2>
16
            <div class="container">
17
                <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
18
                <!-- add your own additional lorem here -->
19
            </div>
20
        </div>
21
    </article>
22
    <footer>
23
        <h3 class="read-next"><small>Read Next:</small><br>How do I Implement a Foobar?</h3>
24
    </footer>
25
</main>

Esto nos da suficiente contenido para probar las funciones de nuestro desplazamiento.

Estilizado Básico

Vamos a usar algunos estilos básicos para hacer nuestra publicación un poco más atractiva.

1
@import url(http://fonts.googleapis.com/css?family=Domine:400,700);
2
body {
3
    font-size: 16px;
4
}
5
h1,
6
h2,
7
h3,
8
h4,
9
h5,
10
h6 {
11
    font-family: "Domine", sans-serif;
12
}
13
14
h1 {
15
    font-size: 3.5em;
16
}
17
18
.lead-in {
19
    color: #fff;
20
    font-weight: 400;
21
    padding: 60px 0;
22
    background-color: #0082FF;
23
}
24
25
article header {
26
    border-top: 3px solid #777;
27
    padding: 80px 0;
28
}
29
30
.article-content {
31
    font-size: 1em;
32
    font-weight: 100;
33
    line-height: 2.4em;
34
}
35
36
p {
37
    margin: 4em 0;
38
}
39
40
.container {
41
    width: 700px;
42
    margin: 0 auto;
43
}
44
45
46
footer {
47
    text-align: center;
48
    background-color: #666;
49
    color: #fff;
50
    padding: 40px 0;
51
    margin-top: 60px;
52
}
53
54
.read-next {
55
    font-size: 2em;
56
}

Estimación de la Posición del Desplazamiento

Para calcular la posición de nuestro desplazamiento, necesitamos entender conceptualmente lo que estamos monitoreando. Ya que JavaScript puede monitorear sólo el valor de desplazamiento superior, necesitaremos supervisar nuestro valor de desplazamiento desde 0 (arriba, sin desplazamiento) hasta cualquier valor final de desplazamiento que sea. El valor final de desplazamiento será igual a la longitud total del documento menos la altura de la ventana (porque el documento se desplazará hasta el fondo del documento hasta que alcance el fondo de la ventana).

Usaremos el siguiente código de JavaScript para calcular está posición de desplazamiento.

1
(function(){
2
    var $w = $(window);
3
    var wh = $w.height();
4
    var h = $('body').height();
5
    var sHeight = h - wh;
6
    $w.on('scroll', function(){
7
        var perc = Math.max(0, Math.min(1, $w.scrollTop()/sHeight));
8
    });
9
10
}());

El código de anterior ajusta la altura de la ventana y la altura del cuerpo y cuando el usuario se desplaza, éste usa esos valores para ajustar una variable perc (abreviatura para porcentaje). Además, vamos a utilizar las clases Math.min y Math.max para limitar los valores hasta el rango 0-100.

Cuando se determina este porcentaje, podemos accionar el indicador de progreso.

Indicador de círculo.

El primer indicador que crearemos es un círculo SVG. Nosotros utilizaremos las propiedades SVG stroke-dasharray y stroke-dashoffset para mostrar el progreso. Primero, vamos a añadir un indicador de progreso al documento.

1
<div class="progress-indicator">
2
    <svg>
3
        <g>
4
            <circle cx="0" cy="0" r="20" class="animated-circle" transform="translate(50,50) rotate(-90)"  />
5
        </g>
6
        <g>
7
            <circle cx="0" cy="0" r="38" transform="translate(50,50)"  />
8
        </g>
9
    </svg>
10
    <div class="progress-count"></div>
11
</div>

Este markup [lenguaje de clasificación de HTML5], nos da dos círculos en un SVG, así como también un div contenedor para mostrar nuestro contador de porcentaje. También, necesitamos añadir estilo a estos elementos y entonces explicaremos como éstos círculos están ubicados y como agregarles animación.

1
.progress-indicator {
2
    position: fixed;
3
    top: 30px;
4
    right: 30px;
5
    width: 100px;
6
    height: 100px;
7
}
8
.progress-count {
9
    position: absolute;
10
    top: 0;
11
    left: 0;
12
    width: 100%;
13
    height: 100%;
14
    text-align: center;
15
    line-height: 100px;
16
    color: #0082FF;
17
}
18
19
svg {
20
    position: absolute;
21
}
22
circle {
23
    fill: rgba(255,255,255,0.9);
24
}
25
26
svg .animated-circle {
27
    fill: transparent;
28
    stroke-width: 40px;
29
    stroke: #0A74DA;
30
    stroke-dasharray: 126;
31
    stroke-dashoffset: 126;
32
}

Estos estilos los configuramos para la animación de nuestros elementos círculos. Nuestro elemento de progreso siempre debería estar visible, así que configuramos la posición para fijarla con .progress-indicator que es una clase con la posición y el tamaño de las reglas. También configuramos nuestro contador de progreso para que éste centrado tanto verticalmente como horizontalmente dentro de este div.

Los círculos están ubicados en el centro usando las propiedades de transformación en los elementos SVG. Iniciamos el centro de nuestro círculos usando transform. Usamos una técnica aquí que nos permite aplicar una rotación desde el centro de nuestros círculos para empezar la animación arriba del círculo (en vez de empezar al lado derecho del círculo). En SVG, transforms son aplicados desde la parte superior izquierda de un elemento. Es por eso que debemos centrar nuestros círculos an 0,0 y mover el centro del círculo al centro del mismo SVG usando translate(50, 50).

Usando stroke-dasharray y stroke-dashoffset

Las propiedades stroke-dasharray y stroke-dashoffset nos permiten animar el contorno de un SVG. stroke-dasharray define las piezas visibles de un contorno. stroke-dashoffset mueve el inicio del contorno. Estos atributos combinados nos permiten crear un proceso de contorno “keyframing”.

Actualizando stroke-dasharray en el Desplazamiento

Luego, añadiremos una función para actualizar el stroke-dasharray, usando nuestro porcentaje de progreso que mostramos anteriormente.

1
(function(){
2
    var $w = $(window);
3
    var $circ = $('.animated-circle');
4
    var $progCount = $('.progress-count');
5
    var wh = $w.height();
6
    var h = $('body').height();
7
    var sHeight = h - wh;
8
    $w.on('scroll', function(){
9
        var perc = Math.max(0, Math.min(1, $w.scrollTop()/sHeight));
10
        updateProgress(perc);
11
    });
12
13
    function updateProgress(perc){
14
        var circle_offset = 126 * perc;
15
        $circ.css({
16
            "stroke-dashoffset" : 126 - circle_offset
17
        });
18
        $progCount.html(Math.round(perc * 100) + "%");
19
    }
20
21
}());

El desplazamiento que coincide con nuestro círculo ocurre a los 126. Es importante considerar que éste no funcionará para todos los círculos, como mide 126 la circunferencia de un círculo con un radio de 20. Para calcular el stroke-dashoffset para un círculo dado, multiplique el radio por 2PI. En nuestro caso, el desplazamiento exacto sería 20 * 2PI = 125.6637614359172.

Variación del Progreso Horizontal

Para nuestro ejemplo, haremos una barra horizontal sencilla que estará fija en la parte superior de la ventana. Para lograr esto, usaremos un div vacío como indicador de progreso.

1
<div class="progress-indicator-2"></div>

Nota: hemos añadido el "-2" para permitirnos incluir este ejemplo en el mismo archivo CSS.

Luego, añadiremos nuestro estilo para este elemento.

1
.progress-indicator-2 {
2
    position: fixed;
3
    top: 0;
4
    left: 0;
5
    height: 3px;
6
    background-color: #0A74DA;
7
}

Finalmente, ajustaremos la anchura de la barra de progreso.

1
var $prog2 = $('.progress-indicator-2');
2
function updateProgress(perc){
3
    $prog2.css({width : perc*100 + '%'});
4
}

Todos juntos, nuestro JavaScript final debería lucir así:

1
(function(){
2
    var $w = $(window);
3
    var $circ = $('.animated-circle');
4
    var $progCount = $('.progress-count');
5
    var $prog2 = $('.progress-indicator-2');
6
    var wh = $w.height();
7
    var h = $('body').height();
8
    var sHeight = h - wh;
9
    $w.on('scroll', function(){
10
        var perc = Math.max(0, Math.min(1, $w.scrollTop()/sHeight));
11
        updateProgress(perc);
12
    });
13
14
    function updateProgress(perc){
15
        var circle_offset = 126 * perc;
16
        $circ.css({
17
            "stroke-dashoffset" : 126 - circle_offset
18
        });
19
        $progCount.html(Math.round(perc * 100) + "%");
20
21
        $prog2.css({width : perc*100 + '%'});
22
    }
23
24
}());

Otras ideas para Barras de Progreso

Este artículo fue diseñado para darle las herramientas e inspiración para diseñar la solución de su barra de progreso. Otras ideas para barras de progreso podrían incluir usando más términos descriptivos o humanizados para la indicación en si, tal como "a mitad de camino” o “apenas comenzando”. Algunas aplicaciones (como el ejemplo de ia.net que mostramos anteriormente) usa una estimación de tiempo para la lectura de un artículo. Esto podría ser estimado usando código similar al siguiente:

1
var wordsPerMin = 300; // based on this article: http://www.forbes.com/sites/brettnelson/2012/06/04/do-you-read-fast-enough-to-be-successful/

2
var wordsArray = $(".article-content").text().split(" ");
3
var wordCount = wordsArray.length;
4
var minCount = Math.round(wordCount / wordsPerMin);

Entonces usted usaría el minCount en conjunto con al variable perc que estamos actualizando en desplazamiento para mostrar al lector su tiempo restante para leer el artículo. Aquí está una implementación básica de este concepto.

1
function updateProgress(perc){
2
    var minutesCompleted = Math.round(perc * minCount);
3
    var remaining = minCount - minutesCompleted;
4
    if (remaining){
5
        $(".progress-indicator").show().html(remaining + " minutes remaining");
6
    } else {
7
        $(".progress-indicator").hide();
8
    }
9
}

Una Pieza Final: Tamaño de Pantalla Flexible

Para asegurarnos que nuestro indicador de progreso funciona como debería, entonces deberíamos asegurarnos que nuestra matemática está calculando las cosas bien en el momento correcto. Para que eso ocurra, necesitamos asegurarnos que estamos volviendo a calcular las alturas y actualizando el indicador de progreso cuando el usuario cambia el tamaño de la ventana.  Aquí está una adaptación de JavaScript parahacer que hacer que eso pase:

1
(function(){
2
    var $w = $(window);
3
  var $circ = $('.animated-circle');
4
	var $progCount = $('.progress-count');
5
	var $prog2 = $('.progress-indicator-2');
6
7
	var wh, h, sHeight;
8
9
	function setSizes(){
10
		wh = $w.height();
11
		h = $('body').height();
12
		sHeight = h - wh;
13
	}
14
15
	setSizes();
16
17
	$w.on('scroll', function(){
18
		var perc = Math.max(0, Math.min(1, $w.scrollTop()/sHeight));
19
		updateProgress(perc);
20
	}).on('resize', function(){
21
		setSizes();
22
		$w.trigger('scroll');
23
	});
24
25
	function updateProgress(perc){
26
		var circle_offset = 126 * perc;
27
		$circ.css({
28
			"stroke-dashoffset" : 126 - circle_offset
29
		});
30
		$progCount.html(Math.round(perc * 100) + "%");
31
32
		$prog2.css({width : perc*100 + '%'});
33
	}
34
35
}());

Este código declara una función que ajusta las variables que necesitamos para calcular el progreso en cual tamaño de pantalla dado, y llama a esa función cuando está cambiando de tamaño. Además, reiniciamos el desplazamiento al cambiar el tamaño de la pantalla para que nuestra función updateProgress sea ejecutada.

¡Ha alcanzado el final!

¿Ha establecido la base para cualquier número de variantes?, ¿qué puede proponer usted? ¿Cuál indicador de progreso ha visto que funcione? ¿Qué le parece los indicadores que son malos para la funcionalidad? ¡Comparta sus experiencias con nosotros en los comentarios!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.