No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Creación de la lógica del gráfico

14/21
Recursos

Aportes 12

Preguntas 0

Ordenar por:

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

Ojo no voy a decir que la explicación esta mal, pero este ejercicio siempre me recuerda que los profesores de programación en general tiene muy mala metodología al explicar la lógica… por lo menos desde mi forma de aprender… un dibujito de vez en cuando para mostrar los pasos del programa no sobra, y da un mejor panorama de lo que va a pasar

Prefiero usar librerías que permite crear los gráficos, ya que la lógica ya esta establecida. Me pareció muy enredada la explicación para la creación de este tipo de componentes.

Lo realice más fácil, respetando que si todos los valores son positivos, partan de 0, o negativos, igual partan de 0.
les dejo mi codigo.

Graphic.vue

<template>
  <div>
    <svg viewBox="0 0 300 200">
      <line
        stroke="#c4c4c4"
        stroke-widt="2"
        x1="0"
        :y1="minmax * max"
        x2="300"
        :y2="minmax * max"
      />
      <polyline fill="none" stroke="#0689B0" stroke-widt="2" :points="points" />
      <line
        stroke="#04b500"
        stroke-widt="2"
        x1="200"
        y1="0"
        x2="200"
        y2="200"
      />
    </svg>
    <p>Ultimos 30 días</p>
    <div>{{ points }}</div>
  </div>
</template>

<script setup>
import { toRefs, defineProps, computed } from "vue";
const props = defineProps({
  amounts: {
    type: Array,
    default: () => [],
  },
});
const { amounts } = toRefs(props);

//minimo por si todos los valores son positivos desde abajo sea 0
const min = Math.min(...amounts.value) < 0 ? Math.min(...amounts.value) : 0;
//maximo por si todos los valores son negativos desde arriba sea 0
const max = Math.max(...amounts.value) > 0 ? Math.max(...amounts.value) : 0;
//el factor para saber el numero de pixeles sobre el monto en altura
const minmax = 200 / (max - min);

//funcion que retorna la posicion en y de 0 a 200
const amountToPixels = (amount) => {
  return (max - amount) * minmax;
};

const points = computed(() => {
  const total = amounts.value.length;
  const xInterval = 300 / total;
  const media = xInterval / 2;
  return amounts.value.reduce((points, amount, index) => {
    const x = xInterval * index + media;
    const y = amountToPixels(amount);
    console.log(y);
    return `${points} ${x},${y}`;
  }, "");
});
</script>

Hola, sin duda el componente del gráfico es el más interesante pero también el más complicado del curso, si sienten que es demasiado para ustedes, no hay ningún problema en saltarse hasta las clases del próximo componente si es necesario.

Recuerden que siempre pueden tomar el código del repositorio del curso si es necesario.

Creo que toda esta sección está de más, ya que lo que se está viendo, no es Vue como tal, sino que como usar JavaScript para graficar usando SVG. Creo que podría ser más interesante, que en este mismo proyecto, hubiésemos consumido una API con valores dummy y así usar alguna librería que los grafique (en el mundo laboral o vida real, el uso de librerías de terceros es imprescindible)

Comparto mi solución

  • Busco el maximo absoluto de entre los montos.
  • Obtengo el porcentaje redondeado del monto absoluto con respecto al maximo absoluto.
  • Partiendo de que Y = 100 es para montos 0, calculo Y 100 - porcentaje para montos positivos, 100 + porcentaje para negativo.
const amountToPixels = (amount) => {
  const min = Math.min(...amounts.value);
  const max = Math.max(...amounts.value);

  const absMax = Math.abs(max) > Math.abs(min) ? Math.abs(max) : Math.abs(min);

  const percentage = Math.round((Math.abs(amount) / absMax) * 100);
  const y = amount < 0 ? 100 + percentage : 100 - percentage;
  return `${y}`;
};
**Explicación de la parte matemática:** La distancia entre los números quiere decir cuantos números hay entre -500 y 200 por ejemplo y para eso hay que sumarlos en valor absoluto y el valor absoluto simplemente es que sean todos los números en positivo. Entonces sacamos **minmax** que es la cantidad total que tenemos. Luego tenemos amountAbs que para sacar un porcentaje es la división entre una parte de una cantidad entre todo lo que hay ejemplo: una clase de 40 niños cuál es el porcentaje si solo cogemos 20 ,pues seria 20/40 que da 1/2 y esto es 0.5 y si lo multiplcas por 100 da 50% y ya tenemos el porcentaje. Qué ocurre, que los pixeles que tenemos no son 100px sino que son 200px asi que para cuadarlo en el gráfico lo multiplicamos por 2 porque lo que se intenta con esto es que la gráfica representa un valor cualquiera dentro del rectángulo gráfico transformando la cantidad total de 0-100 que es un porcentaje.

Gracias por sus comentarios mataron el video

por que no utilizamos una libreria de graficas y listo? saben cuantos estudiantes va a salir corriendo despues de esta clase!

Esta función es mucho más sencilla:

const amountToPx = (amount) => {
    const min = Math.min(...amounts.value);
    const max = Math.max(...amounts.value);
    return 200 - ((amount - min) / Math.abs(max - min)) * 200;
};

.
Recordar que deben agregar el valor inicial al .reduce con su pixel en la posición cero:

const x0 = amountToPx(amounts.value[0]);

return amounts.value.reduce(() => {
	// code
}, `0,${x0}`);

Les comparto mi funcion para normalizar

type Range ={min: number, max:number}
export function normalizeRange (from: Range, to: Range) {
  const fromHeight = Math.abs(from.max - from.min) // 16
  const toHeight = Math.abs(to.max - to.min) // 200
  return function normalizeRange (value: number) {
    // Movemos movemos el valor para hacerlo relativo a cero
    const valueFromZero = (value - from.min) // 16
    // Obtenemos el porcentage relativo al tamaño del origen
    const valuePercentage = valueFromZero / fromHeight // 1
    // Convertimos a los valores del target
    const targetSize = valuePercentage * toHeight // 200
    // Agregamos el offset de min
    const result = targetSize + to.min // 200
    return result
  }
}

// uso 

const yNormalizer = normalizeRange({ min, max }, { min: 0, max: 200 })
const y = yNormalizer(amount)