Hero View

22/27

Lectura

Ahora que tenemos la página de Profile completa, y podemos navegar a la Hero, vamos a crear las funciones y componentes necesarios para esta vista.

...

Regístrate o inicia sesión para leer el resto del contenido.

Aportes 10

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

En respuesta a la pregunta de la clase: Si se le coloca esa propiedad a algún elemento de recurso sucede que la imagen se descoloca y se visualizan 4 recursos pero todos recordados de mala forma. Al estar trabajando con 1 sola imagen para todos los recursos el posicionamiento debería ser el adecuado y la linea que se le añade lo distorsiona.

Vaya fumada de clase, casi que no la saco adelante :c

Bufff, este bloque estuvo largo pero logré entenderlo, hubo un punto en el que me frustré porque habían componentes sin contenido y no podía ver los resultados:( Pero todo genial hasta ahora, aunque en la página en producción no se ven las habilidades pasivas ni las imágenes…

Pensé que el tema se refería a algo parecido a Hero Widget como en Flutter, me alegré muchísimo pensando eso, pero nada que ver

Vi que en utilizas el forEach y map, ¿En qué casos debo utilizar uno el otro? , Siempre me causa conflicto en cual situación debo utilizarlo

En la sección dónde agrega el componente HeroDetailHeader, se muestran mal las etiquetas HTML.

Vaya clase! bastante contenido, pero al final de tanto analizar se entiende bien…
Solo una observación…

Cuando nos piden que importemos los componentes de atributos y habilidades y los registremos los mismos en el /Hero/Index.vue.

Nos indican importar el ‘HeroItems’

import HeroAttributes from './HeroAttributes/Index'
import HeroItems from './HeroItems/Index'

Pero registramos el ‘HeroSkills’

components: {
  BaseLoading,
  HeroDetailHeader,
  HeroAttributes,
  HeroSkills
}

En mi caso imaginé que la importación pertenecia al HeroSkills ya que comenzamos a trabajar con el posteriormente, de igual forma está un poco confuso, si lo pudieran aclarar les agredezco!

Si las imagenes no les cargan es porque en el la url falto un / justo en esta parte

const host = `http://media.blizzard.com/d3/icons/skills/${sizes[1]}`

al final de la url debe ir el / ya que la url debe ser asi

http://media.blizzard.com/d3/icons/<type>/<size>/<icon>.png

no asi

http://media.blizzard.com/d3/icons/<type>/<size><icon>.png

Cada vez se ha vuelto mas complejo, pero todo bien!

Crei que nunca acabaria esta leccion no entiendo nada del juego pero si el codigo casi todo 😄

Vayamos por partes. Lo primero, importar el mixin de error y el componente Loading. En caso de error, usaremos el mixin. Mientras hagamos las llamadas a las APIs, usaremos el componente Loading hasta que se carguen los datos. Como tenemos dos llamadas de APIs (hero & items) distintas vamos a tener dos componentes Loading, uno para cada llamada.En la sección de variables, hemos definido la variable hero y la variable items. Las dos llamadas que vamos a hacer son independientes la una de la otra, por lo tanto se van a hacer en paralelo. Por eso hemos incluido otras dos variables de control para saber si están loading o no:data () { return { isLoadingHero: false, isLoadingItems: false, hero: null, items: null }}Lo siguiente es hacer las llamadas a las dos APIs. Ponemos el loading a true, llamamos a las APIs.En caso de error hacemos uso del mixin y si todo va bien, guardamos el resultado en la variable correspondiente.Por último, ponemos los loading a false. Con esto vamos a poder controlar la visibilidad del componente de Loading.Vemos que, efectivamente, se están haciendo las dos llamadas a las APIs:Ahora que ya tenemos los datos necesarios, vamos a empezar con los componentes de la vista. La estructura de componentes que vamos a seguir es esta:> 📗 Si nunca has jugado a Diablo III, te recomiendo que leas esta guía de controles de combate: https://eu.diablo3.com/es/game/guide/gameplay/combat-skillsPersonalmente, creo que esta es la página más divertida de toda la app 🤙🤩🎉.Vamos a pintar en pantalla:Los atributos (fuerza, vida, inteligencia, etc.) del personaje, incluyendo sus recursos:Recursos:Sus habilidades, tanto las activas como las pasivas (si las tiene, depende del nivel del personaje) y las runas (en caso de que tenga alguna, también dependen del nivel).En esta parte veremos como crear componentes asíncronos (parecido a lo que hacíamos con las rutas y el lazy load, solo serán cargados cuando se requieran)Los objetos, junto con las joyas o gemas que puedan tener engarzadas.Para los objetos, pintaremos una barra de color según la calidad de los objetos: https://eu.diablo3.com/es/game/guide/items/equipment#item-qualityColor blanco: NormalColor azul: MágicoColor amarillo: RaroColor verde: Conjunto (otorgan bonificación extra cuando llevas el set completo)Color naranja: LegendariosVamos a construir algo parecido a esto, que es como se ven los objetos del personaje (en PC, para consola cambia):Aquí hay objetos azules (mágicos) y amarillos (raros). Además vemos algunas gemas, por ejemplo, en el arma. Algo parecido a esto es lo que vamos a construir con los datos que nos devuelva la API de items.Lo primero es crear la estructura de carpetas. ¡Empecemos!Vamos a /views/Hero y creamos tres carpetas: HeroAttributes, HeroItems y HeroSkills. Creamos también el componente HeroDetailHeader.vue, que no va a estar agrupado en carpetas. Deberías tener una estructura como esta:📂 /Hero├──📂 /HeroAttributes├──📂 /HeroItems├──📂 /HeroSkills├── HeroDetailHeader.vue└── Index.vueAhora, en nuestro componente /Hero/Index.vue, traemos el componente HeroDetailHeader:import HeroDetailHeader from './HeroDetailHeader'Y lo damos de alta para poder usarlo:components: { BaseLoading, HeroDetailHeader}Usamos los componentes:> Por ahora, ignora los erroresLos datos que necesita el componente HeroDetailHeader son los siguientes: name, class, gender, level, hardcore, seasonal, paragonLevel, alive y seasonCreated. Todos estos datos los sacamos de la variable this.hero, que es donde guardamos los datos que hemos recuperado de la API.Creamos una computed llamada detailHeader que nos retorne estos valores:computed: { detailHeader () { // Asignamos valores a través de const { name, // valor: alias class: classSlug, gender, level, hardcore, seasonal, paragonLevel, alive, seasonCreated } = this.hero return { name, classSlug, gender, level, hardcore, seasonal, paragonLevel, alive, seasonCreated } }}> 📗 Asignación por desestructuración: https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Operadores/Destructuring_assignmentEsto es lo que recibe el componente HeroDetailHeader en la prop detail.Ahora, abrimos el recién creado componente de HeroDetailHeader y le damos este contenido:JavaScriptCon la computed heroClass vamos a crear la clase de CSS necesaria para mostrar la cara correspondiente a nuestro personaje. Ya lo hemos usado con anterioridad; estamos usando las mismas clases para generar el avatar de nuestro héroe.CSS:HTMLEn el HTML lo único que estamos haciendo es pintar, en el centro, los datos que recibimos del componente padre.Si todo va bien, deberías ver algo como esto:Con esto hemos terminado el componente de detailHeader. A continuación vamos a trabajar con el componente de Atributos.Volvemos al componente /Hero/Index.vue y ponemos lo siguiente en el HTML:El componente de DetailHeader está a 12 columnas (es decir el 100%). Para los demás componentes vamos a crear 2 columnas, como vimos en una imagen anteriormente. A la izquierda (atributos y habilidades) una columna de 4 unidades (sobre 12) y a la derecha (objetos) otra columna de 8 (sobre 12).En tamaño de pantalla pequeño, lo primero que veremos es el bloque de 8 columnas, es decir, los objetos del personaje. Pero para pantallas grandes estamos alterando el orden de aparición a con la propiedad order de flexbox: https://bootstrap-vue.js.org/docs/components/layout/#reordering.Seguimos en /Hero/Index.vue. Importamos los componentes de atributos y habilidades y los registramos:import HeroAttributes from './HeroAttributes/Index'import HeroItems from './HeroItems/Index'components: { BaseLoading, HeroDetailHeader, HeroAttributes, HeroSkills}El componente de Skills recibe el dato intacto de hero.skills. Para el componente de Attributes necesitamos crear una computed que haga alguna transformación. En este caso la transformación es muy simple. Cogemos los datos de hero.stats y le agregamos la clase (tipo) de personaje, que la necesitaremos en un componente hijo más adelante:computed: { detailStats () { // Devuelve el contenido de stats y agrega classSlug return { ...this.hero.stats, classSlug: this.hero.class } }}Para evitar errores en consola, vamos a crear también el fichero de HeroSkills. Dentro de la carpeta creamos su Index.vue correspondiente y le damos este contenido:/Hero/HeroSkills/Index.vueCon esto ya podemos ir a pintar los componentes de atributos (y también de habilidades).Dentro de HeroAttributes tendremos tres componentes: atributos primarios, atributos secundarios y recursos.Vamos a crear el componente Index.vue en la carpeta /HeroAttributes, que está vacía. Además, dentro la misma, creamos otros dos componentes: HeroAttributeList.vue y HeroResources.vueAbrimos /HeroAttributes/Index.vue y agregamos lo siguiente:Los arrays que acabamos de definir nos sirven para agrupar las claves que necesitamos en cada bloque.Hemos agrupado en atributos principales (core), secundarios y recursos.Todos los héroes tienen vida y recurso primario, pero solamente algunos tienen recurso secundario.El HTML, que también es bastante sencillo, es el siguiente:Para que te hagas la idea, un ejemplo de atributos primarios serían estos:[ { 'name':'strength', 'val':77 }, { 'name':'dexterity', 'val':77 }, { 'name':'vitality', 'val':4813 }, { 'name':'intelligence', 'val':9660 }]Hemos definido fuerza, destreza, vitalidad e inteligencia como atributos primarios. Solo nos quedaría mostrarlos por pantalla.Un ejemplo de atributos secundarios serían estos:[ { 'name':'damage', 'val':986514 }, { 'name':'toughness', 'val':15263800 }, { 'name':'healing', 'val':1305200 }]Daño, dureza y curación serían nuestros atributos secundarios. Como ves, son idénticos a los primarios (a nivel de estructura de datos) y por lo tanto podemos utilizar el mismo componente para pintar los dos tipos de atributos. Simplemente les pasamos distinta información, pero mismo formato.El componente /Hero/HeroAttributes/HeroAttributeList.vue es muy sencillo. Lo único que hace es mostrar el nombre del atributo (en color naranja) y su valor (en color blanco), pasado por el filtro de numeral (que ya hemos usado anteriormente):La app, actualmente, se ve así aunque tengamos errores:RecursosTodas las clases tienen, además de los puntos de vida (HP), un recurso propio. Los recursos son: furia (bárbaro), cólera (cruzado), odio y disciplina (cazador de demonios), esencia (nigromante), espíritu (monje), maná (médico brujo) y poder arcano (mago).En este bloque, vamos a pintar los puntos de vida que tiene el personaje y su recurso correspondiente. Tenemos cargados todos los recursos (incluyendo la vida) en una imagen, a modo de sprite. Esta es la imagen que usaremos:Vamos a crear las clases CSS correspondientes para cada tipo de héroe.¿Recuerdas en dónde tenemos los estilos globales de CSS? Si pensaste que era /src/assets/css/main.styl, has acertado. Abrimos el archivo y le agregamos lo siguiente:// ---------------------// Resources// ---------------------.resource .resource-icon background-image url('../img/resources.png') width 50px height 50px &.resource-mana background-position 0 -50px &.resource-fury background-position: -50px 0 &.resource-hatred-discipline background-position: -100px 0px &.resource-spirit background-position: -50px -50px &.resource-arcane-power background-position: -100px -50px &.resource-wrath background-position: 0px -100px &.resource-essence background-position: -50px -100pxComo has podido ver, es muy sencillo este bloque de CSS. Cargamos la imagen y nos vamos moviendo de 50 en 50 por la imagen 😃 según el recurso que seleccionemos.Al igual que hemos hecho antes con los nombres de los héroes, vamos a crear un mixin para mostrar el nombre normalizado de los recursos. Para ello vamos a la carpeta donde están los mixins y creamos un nuevo fichero. De nombre le ponemos resources.js y el contenido va a ser el siguiente:const names = { BARBARIAN: 'barbarian', CRUSADER: 'crusader', MONK: 'monk', WIZARD: 'wizard', WITCHDOCTOR: 'witch-doctor', NECROMANCER: 'necromancer', DEMONHUNTER: 'demon-hunter'}const resourceClassName = { [names.BARBARIAN]: 'fury', [names.CRUSADER]: 'wrath', [names.MONK]: 'spirit', [names.WIZARD]: 'arcane-power', [names.WITCHDOCTOR]: 'mana', [names.NECROMANCER]: 'essence', [names.DEMONHUNTER]: 'hatred-discipline'}const resourceDisplayName = { [names.BARBARIAN]: 'Fury', [names.CRUSADER]: 'Wrath', [names.MONK]: 'Spirit', [names.WIZARD]: 'Arcane Power', [names.WITCHDOCTOR]: 'Mana', [names.NECROMANCER]: 'Essence', [names.DEMONHUNTER]: 'Hatred / Discipline'}export default { methods: { /** * Get the name of the primary resource by class * @param classSlug {String} * @returns {String} */ resourceClassName (classSlug) { return resourceClassName[classSlug] }, /** * Resource Normalized name * @param classSlug {String} * @returns {String} */ resourceDisplayName (classSlug) { return resourceDisplayName[classSlug] } }}Regresamos al componente de recursos, abrimos el archivo /HeroAttributes/HeroResources.vue y ponemos lo siguiente:Recibimos datos a través de una prop y los mostramos, eso es todo lo que hacemos aquí. Con esto funcionando, la app debería verse así:Ahí vemos la esencia , que es el recurso del nigromante. Si probamos a cambiar de clase, vemos que se carga el recurso correspondiente. En los ejemplos de abajo vemos la ira del cruzado y el odio / disciplina del cazador de demonios.> ✏️ Ves al navegador y prueba a cambiar los estilos CSS de la imagen de los recursos.> ¿Qué pasa si pones background-position: -25px 75px; al elemento un recurso cualquiera? Deja tus respuestas en el sistema de comentariosCon esto ya hemos terminado el bloque de atributos y recursos del personaje. Vamos a seguir con la siguiente parte, que es la de habilidades.SkillsCada personaje puede tener hasta 6 habilidades activas, 2 de ratón (botón primario y secundario) y 4 de teclado. Las habilidades se van desbloqueando según el nivel, no tienes todas las habilidades disponibles desde el inicio.A su vez, las habilidades activas pueden tener modificadores o runas de habilidad que mejoren dicha habilidad. Al igual que con las habilidades, las runas se van desbloqueando cuando vas subiendo de nivel.Todo esto corresponde a las habilidades activas. Existen otro grupo de habilidades, las habilidades pasivas. Como las demás, se van ganando al subir de nivel.Aquí puedes ver, a modo ejemplo, el progreso de niveles y habilidades del nigromante: https://eu.diablo3.com/es/class/necromancer/progressionUna vez entendido esto, podemos ir a crear los componentes necesarios. Vamos a tener componentes agrupados en habilidades activas y habilidades pasivas.¡Hagámoslo! Dentro de nuestra carpeta de /Hero/HeroSkills creamos los siguientes archivos: ActiveSkills.vue, ActiveSkill.vue, PassiveSkills.vue y PassiveSkill.vue.El contenido de /Hero/HeroSkills/Index.vue va a ser el siguiente (de momento):Estamos cargando los skills activos y los pasivos, sin más.Vamos a editar los componentes de las habilidades, empezando por el habiliades activas.Como tenemos un array de skills lo que vamos a hacer es iterar, con v-for, para utilizar el componente de habilidad individual, ActiveSkill.ActiveSkills.vue:Antes de cargar el listado de habilidades activas, necesitamos editar el fichero global de CSS, que es dónde estamos guardando los estilos para los Sprites de imágenes.Para identificar qué habilidad estamos mostrando, vamos a agregar estas líneas de código en /assets/css/main.styl:// ---------------------// Active Skills// ---------------------.active-skills .skills .slot display block width 22px height 22px background url('../img/skill-overlays.png') 0 0 position absolute top -5px left 5px &.slot-1 background-position: 0 -1px &.slot-2 background-position: -21px -1px &.slot-3 background-position: 0 -23px &.slot-4 background-position: -23px -23px &.slot-5 background-position: 0 -46px &.slot-6 background-position: -23px -46pxCon slot nos estamos refiriendo a qué habilidad es, siendo slot-1 el botón principal del ratón y slot-2 el botón secundario. Aguanta un poco, que con un ejemplo lo verás mejor.lActiveSkill.vue:Skill ImagesEn las propiedades estamos recibiendo la habilidad, la runa en caso de que la tenga (si no llega, no la mostramos) y el número de slot, que corresponde con las clases de CSS que hemos creado recientemente.> 📗 Documentación para obtener las URLs de las habilidades y de los objetos de Diablo III: https://develop.battle.net/documentation/diablo-3/community-apisHacemos la composición de la URL, tenemos la base de la URL, el tipo (skills), el tamaño (42) y el nombre del icon (que nos lo da la API).Un ejemplo sería este: http://media.blizzard.com/d3/icons/skills/42/p6_necro_bonespikes.pngQue renderiza esta imagen:Gracias al atributo title, si pasamos el ratón por encima del elemento, podemos ver una breve descripción.Perfecto, ya tenemos las habilidaes activas de nuestro personaje cargadas, que se ven así en nuestra app:Hora de cargar las habilidades pasivas, que son casi lo mismo que las activas, pero más sencillas. Solo imagen y nombre de la habilidad.PassiveSkills.vue:PassiveSkill.vue:Bien, ya tenemos las habilidades activas y las pasivas funcionando. Se deberían ver así:Puede darse el caso en el que si estás usando el perfil de un personaje que no está al nivel máximo, no tengas todas las habilidades (activas, pasivas y runas) desbloqueadas y por lo tanto veas menos habilidades.Con esto hemos terminado la parte de skills… en modo normal. En el siguiente bloque vamos a ver cómo refactorizar el bloque de habilidades y crear componentes asíncronos dinámicos 🤘.", "url" : "https://platzi.com/clases/1856-avanzado-vue/27768-hero-view/", "wordCount" : "52", "publisher" : { "type" : "Organization", "name" : "Platzi INC" } }