• code
  • wordpress
  • heroes
  • community
  • developers
  • inspire
Loaded
Post Image

En este artículo te explicamos como construir un modelo de avatar a través de imágenes estáticas incluidas en HTML y animarlo gracias a JQuery y las habilidades de síntesis de voz del navegador.

En general se trata de un gran trabajo de diseño inicial y después se unen las piezas en código para poder ir dando forma a nuestro avatar. Aunque este artículo lo escribe Cristina, es un trabajo conjunto de varios profesionales de WordPress Heroes.

Te dejamos un ejemplo para que puedas utilizarlo como guía inicial. Lo ideal es que apliques el código a tus propias creaciones y desarrolles nuevos efectos y animaciones. Puedes compartir tu experiencia en los comentarios.

Crear un diseño base para el avatar

En primer lugar tendrás que generar una serie de elementos que configurarán nuestro avatar. En nuestro caso hemos desarrollado varias piezas que luego unimos en el código. Brazo izquierdo, brazo derecho, pierna izquierda, pierna derecha, tronco, ojo derecho…

En total tenemos preparados 29 elementos que conforman nuestro avatar. Ten en cuenta que incluso cada pupila tiene su elemento independiente para dar más realismo al muñeco.

Si preparas tus propias piezas para tu avatar tendrás que utilizar siempre una referencia sobre la que colocar cada parte del puzzle. El brazo derecho ocupará su lugar en un espacio. Por ejemplo si te fijas en la siguiente imagen verás que las cejas están colocadas en una transparencia justamente en la posición por encima de los ojos. Superponiendo todas las imágenes en orden tendremos nuestro avatar completo.

Te dejamos un archivo descargable comprimido para que pueda utilizar todas las imágenes.

Disponible muy pronto…

Esta parte puede ser la más compleja si no eres experto en diseño. Nosotros trabajamos con Gimp habitualmente y los resultados son muy buenos. No obstante, es necesaria cierta experiencia, sobre todo para utilizar las transparencias y dejar las imágenes ajustadas.

Incluir las imágenes del Avatar en HTML 5

Una vez que tengas todas las piezas del puzzle preparadas nos toca incluirlas en nuestra web a través de HTML 5. Para ello utilizaremos el siguiente código que emplea funciones del núcleo WordPress.

Código para estructura física de nuestro Avatar
<div class="wph-avatar-wrapper">
  <div class="wph-avatar position-relative">
    <div class="wph-avatar-image glasses-red display-none">
      <?php echo wp_get_attachment_image(1695, 'full'); ?>
    </div>
    <div class="wph-avatar-image glasses-black display-none">
      <?php echo wp_get_attachment_image(1710, 'full'); ?>
    </div>
    <div class="wph-avatar-image glasses-blue display-none">
      <?php echo wp_get_attachment_image(1711, 'full'); ?>
    </div>
    <div class="wph-avatar-image helmet display-none">
      <?php echo wp_get_attachment_image(1713, 'full'); ?>
    </div>
    <div class="wph-avatar-image arm arm-right">
      <?php echo wp_get_attachment_image(1701, 'full'); ?>
    </div>
    <div class="wph-avatar-image arm arm-right arm-jar-right display-none">
      <?php echo wp_get_attachment_image(1698, 'full'); ?>
    </div>
    <div class="wph-avatar-image arm arm-left">
      <?php echo wp_get_attachment_image(1699, 'full'); ?>
    </div>
    <div class="wph-avatar-image arm arm-left arm-jar-left display-none">
      <?php echo wp_get_attachment_image(1697, 'full'); ?>
    </div>
    <div class="wph-avatar-image legs">
      <?php echo wp_get_attachment_image(1714, 'full'); ?>
    </div>
    <div class="wph-avatar-image chest">
      <?php echo wp_get_attachment_image(1696, 'full'); ?>
    </div>
    <div class="wph-avatar-image face">
      <?php echo wp_get_attachment_image(1709, 'full'); ?>
    </div>
    <div class="wph-avatar-image face eye eyebrows">
      <?php echo wp_get_attachment_image(1702, 'full'); ?>
    </div>
    <div class="wph-avatar-image face eye eye-closed eye-closed-right display-none">
      <?php echo wp_get_attachment_image(1704, 'full'); ?>
    </div>
    <div class="wph-avatar-image face eye eye-closed eye-closed-left display-none">
      <?php echo wp_get_attachment_image(1703, 'full'); ?>
    </div>
    <div class="wph-avatar-image face eye eye-right eye-right">
      <?php echo wp_get_attachment_image(1708, 'full'); ?>
    </div>
    <div class="wph-avatar-image face eye eye-right eye-pupil eye-pupil-right">
      <?php echo wp_get_attachment_image(1707, 'full'); ?>
    </div>
    <div class="wph-avatar-image face eye eye-left eye-left">
      <?php echo wp_get_attachment_image(1705, 'full'); ?>
    </div>
    <div class="wph-avatar-image face eye eye-left eye-pupil eye-pupil-left">
      <?php echo wp_get_attachment_image(1706, 'full'); ?>
    </div>
    <div class="wph-avatar-image face mouth mouth-closed-smile display-none">
      <?php echo wp_get_attachment_image(1715, 'full'); ?>
    </div>
    <div class="wph-avatar-image face mouth mouth-closed display-none">
      <?php echo wp_get_attachment_image(1716, 'full'); ?>
    </div>
    <div class="wph-avatar-image face mouth mouth-smile display-none">
      <?php echo wp_get_attachment_image(1718, 'full'); ?>
    </div>
    <div class="wph-avatar-image face mouth mouth-talking mouth-talking-4 display-none">
      <?php echo wp_get_attachment_image(1694, 'full'); ?>
    </div>
    <div class="wph-avatar-image face mouth mouth-talking mouth-talking-3 display-none">
      <?php echo wp_get_attachment_image(1722, 'full'); ?>
    </div>
    <div class="wph-avatar-image face mouth mouth-talking mouth-talking-2 display-none">
      <?php echo wp_get_attachment_image(1721, 'full'); ?>
    </div>
    <div class="wph-avatar-image face mouth mouth-talking mouth-talking-1">
      <?php echo wp_get_attachment_image(99, 'full'); ?>
    </div>
    <div class="wph-avatar-image face hair">
      <?php echo wp_get_attachment_image(1712, 'full'); ?>
    </div>
  </div>
</div>

Y además incluiremos el siguiente código CSS que regula los estilos de nuestro avatar. Fundamentalmente emplea la propiedad position:absolute; para todas las imágenes de forma que se superpongan entre sí.

Código para estilos de nuestro Avatar

.wph-avatar-image img{
  position: absolute!important;
}

@media all and (max-width:768px){
  .wph-avatar-wrapper{
    width: 80px;
    top: 180px;
  }
}

Como puedes ver simplemente se genera una estructura div global que incluye cada una de las imágenes de nuestro avatar. Para cargar las imágenes empleamos la función de WordPress wp_get_attachment_image con la que llamamos a la imagen que contiene un ID determinado.

Previamente hemos subido cada una de las imágenes a nuestra instalación a través del gestor de archivos multimedia del propio panel de administración de WordPress.

Uno de los detalles fundamentales de este código es la elección de las clases HTML de cada imagen. Por ejemplo, en los elementos que corresponden a la cara incluimos la clase face, las imágenes que se asocian con un ojo incluyen la clase eye…

Luego cada imagen tiene una clase particular que la diferencia. Hay una imagen que tiene las clases wph-avatar-image, face, eye, eye-left, eye-pupil y eye-pupil-left. Cada una de ellas nos servirá después para generar las animaciones en JQuery apropiadas para cada elemento.

Por supuesto en cada imagen está incluida la clase wph-avatar-image que es la que rige los estilos de posición que comentabamos antes para que todo el avatar esté integrado.

Un aspecto importante que no podemos olvidar es el orden en el que se cargan las imágenes. HTML va incluyendo imágenes a medida que las lee en el código, por lo que las primeras imágenes en la lista serán las que queden por debajo de las siguientes.

Esto es clave a la hora de incluir cada imagen para saber dónde quedará luego dentro de la visualización. Si ponemos la imagen correspondiente al ojo antes que la de la cara resultará en que el ojo no se verá porque lo ocultará el óvalo que corresponde a la imagen de la cara.

Añadir animaciones a un Avatar mediante Jquery

Una vez que tenemos la fisonomía completa de nuestro avatar pasamos a darle vida. Para ello utilizaremos el lenguaje de cliente JQuery, basado en JavaScript.

Simplemente iremos llamando a cada una de las clases con las que hemos denominado a cada imagen y jugaremos con ellas, animándolas con diferentes propiedades CSS para crear la magia.

El código completo que hemos preparado para la animación que ves del avatar es el siguiente. No te asustes. Se trata del código más complejo de todos puesto que incluye muchos tipos diferente de interacciones con CSS y con los elementos del DOM que dan vida al avatar. Lo explicamos más abajo por partes.

Código para animaciones de nuestro Avatar
jQuery(document).ready(function($) {
  function wph_avatar_rotate(targetElement, speed, angle_initial, angle_final){
    $({deg: angle_initial}).animate({deg: angle_final}, {
      duration: speed,
      step: function(now) {
        targetElement.find('img').css({
          transform: 'rotate(' + now + 'deg)'
        });
      }
    });
  };

  function wph_avatar_blink(target_eye = 'both', speed = 200){
    setTimeout(function(){
      $('.eye:not(.eye-closed):not(.eyebrows)' + (target_eye != 'both' ? ':not(.eye-' + target_eye + ')' : '')).addClass('display-none');
      $('.eye-closed').removeClass('display-none');
      $('.wph-avatar-image.eyebrows img').animate({top:'+1px'}, 100);
    }, 500);
    setTimeout(function(){
      $('.eye-closed').addClass('display-none');
      $('.eye:not(.eye-closed):not(.eyebrows)' + (target_eye != 'both' ? ':not(.eye-' + target_eye + ')' : '')).removeClass('display-none');
      $('.wph-avatar-image.eyebrows img').animate({top:'-1px'}, 100);
    }, 500 + speed);
  };

  function wph_avatar_arms(target_arm = 'left'){
    var random = Math.floor((Math.random() * $('.arm-' + target_arm + ':not(.arm-ok)').length));
    $('.arm-' + target_arm + ':not(.arm-ok)').addClass('display-none');
    $('.arm-' + target_arm + ':not(.arm-ok)').eq(random).removeClass('display-none');
  };

  function wph_avatar_eyebrows(distance, speed){
    $('.wph-avatar-image.eyebrows img').animate({top:'-' + distance + 'px'}, speed);
    $('.wph-avatar-image.eyebrows img').queue(function() {
      $('.wph-avatar-image.eyebrows img').animate({top:'+' + distance + 'px'}, speed);
      $(this).dequeue();
    });
  };

  function wph_avatar_pupils(speed){
    $('.wph-avatar-image.eye-pupil img').animate({left:'+1px'}, speed);
    $('.wph-avatar-image.eye-pupil img').queue(function() {
      $('.wph-avatar-image.eye-pupil img').animate({left:'-1px'}, speed);
      $(this).dequeue();
    });
  };

  function wph_avatar_mouth(){
    var random = Math.floor((Math.random() * $('.wph-avatar-image.mouth').length));
    $('.wph-avatar-image.mouth').addClass('display-none');
    $('.wph-avatar-image.mouth').eq(random).removeClass('display-none');
  };

  function wph_avatar_talking(){
    var random = Math.floor((Math.random() * $('.wph-avatar-image.mouth-talking').length));
    $('.wph-avatar-image.mouth').addClass('display-none');
    $('.wph-avatar-image.mouth-talking').eq(random).removeClass('display-none');
  };

  function speak(text, callback) {
    var utterance = new SpeechSynthesisUtterance();
    utterance.text = text;
    utterance.lang = 'es-ES';
    utterance.rate = 1;
    var wph_speak_interval = setInterval(function(){
      wph_avatar_talking();
    }, Math.floor((Math.random() * 150) + 150));
  
    utterance.onend = function () {
      wph_avatar_mouth();
      clearInterval(wph_speak_interval);
      if (callback) {
        callback();
      }
    };
 
    utterance.onerror = function (e) {
      if (callback) {
        callback(e);
      }
    };
 
    speechSynthesis.speak(utterance);
  }

  function wph_avatar_idle(){ 
    /*wph_avatar_breathe($('.wph-avatar-image.chest img'), Math.floor((Math.random() * 2000) + 2000));*/

    setInterval(function(){
      setTimeout(function(){wph_avatar_rotate($('.wph-avatar-image.face'), Math.floor((Math.random() * 2000) + 2000), 4, 0);}, 1000);
      setTimeout(function(){wph_avatar_rotate($('.wph-avatar-image.face'), Math.floor((Math.random() * 2000) + 2000), 0, 4);}, 5000);
    }, 10000);

    setInterval(function(){
      setTimeout(function(){wph_avatar_rotate($('.wph-avatar-image.arm-right'), Math.floor((Math.random() * 2000) + 2000), 1, 0);}, 1000);
      setTimeout(function(){wph_avatar_rotate($('.wph-avatar-image.arm-right'), Math.floor((Math.random() * 2000) + 2000), 0, 1);}, 3000);
    }, 9000);

    setInterval(function(){
      setTimeout(function(){wph_avatar_rotate($('.wph-avatar-image.arm-left'), Math.floor((Math.random() * 2000) + 2000), 1, 0);}, 3000);
      setTimeout(function(){wph_avatar_rotate($('.wph-avatar-image.arm-left'), Math.floor((Math.random() * 2000) + 2000), 0, 1);}, 4000); 
    }, 11000);

    setInterval(function(){wph_avatar_blink();}, Math.floor((Math.random() * 2000) + 3000));
    setInterval(function(){wph_avatar_pupils(1000);}, Math.floor((Math.random() * 1000) + 5000));
    setInterval(function(){wph_avatar_mouth();}, Math.floor((Math.random() * 5000) + 7000));
    setInterval(function(){wph_avatar_arms('left');}, Math.floor((Math.random() * 2000) + 3500));
    setInterval(function(){wph_avatar_arms('right');}, Math.floor((Math.random() * 1000) + 3000));
  };

  wph_avatar_idle();
  setTimeout(function(){speak('Marina, muchas felicidades Naná por tus cuatro añitos.', false);}, 3000);
});

En general verás que hay funciones para cada parte del cuerpo. Hay una función que se encarga de la boca, otra que se encarga de las pupilas, otra del movimiento de la cabeza…

Hemos empleado muchos elementos aleatorios para darle diferentes periodos a los movimientos. Verás que se calculan al azar rangos de tiempo que rigen la amplitud de algunos movimientos o su duración. Esto hace que sea más atractivo para el usuario que lo ve y no sea una simple repetición de patrones.

Una de las funciones, la que hace al avatar hablar, las explicaremos con más detalle en otro artículo del blog. En el resto de funciones la más interesante es wph_avatar_idle que es la que conecta todas y pone en marcha el proceso de movimientos.

Como ves se emplea mucho setInterval y setTimeout que son dos funciones JavaScript fundamentales para jugar con los tiempos de respuesta de los elementos del DOM, tanto temporizándolos como creando repeticiones.

Si quieres entender cada función en detalle tendrás que ir estudiándola en profundidad y ver sus interacciones con el resto.

Prev
Gestionar el sistema Cron en WordPress
Next
No more posts

close
close
close

Eliminación de tareas

La tarea se eliminará por completo. Este proceso no se puede revertir y la tarea no se puede recuperar.

Password strength checker close

  • radio_button_unchecked Lowercase & Uppercase
  • radio_button_unchecked Number (0-9)
  • radio_button_unchecked Special Character (!@#$%^&*)
  • radio_button_unchecked Atleast 8 Character
close
close