File size: 3,012 Bytes
0dc7194 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | /**
* Modulo de visualizacion de graficos usando Chart.js.
*
* Responsabilidades:
* - renderDetailChart(canvasId, currentPrice) → grafico de linea 7d con sparklines.
* - renderSparkline(containerId, price, side) → barras verticales animadas (YES/NO).
*
* Datos:
* - Los puntos se generan sinteticamente con ruido aleatorio alrededor del precio actual.
* - Color verde si precio > 50¢, rojo si < 40¢, naranja en medio.
*
* Consumido por:
* - app.js → al renderizar el panel de detalle de un mercado.
*/
import { Chart } from 'chart.js/auto'
let detailChartInstance = null
export function renderDetailChart(canvasId, currentPrice, history = []) {
const ctx = document.getElementById(canvasId)
if (!ctx) return
if (detailChartInstance) detailChartInstance.destroy()
const container = ctx.parentElement
if (container) {
const labelEl = container.querySelector('.chart-label')
const labelH = labelEl ? labelEl.offsetHeight + 6 : 24
ctx.style.height = `${container.clientHeight - labelH - 28}px`
}
let pts, labels
if (history.length >= 2) {
pts = history.map((h) => +(h.p * 100).toFixed(2))
labels = history.map((h) => {
const d = new Date(h.t * 1000)
return `${d.getMonth() + 1}/${d.getDate()} ${d.getHours()}h`
})
} else {
const base = currentPrice * 100
pts = Array.from({ length: 8 }, (_, i) => {
const noise = (Math.random() - 0.5) * 8
return Math.max(5, Math.min(95, base - 12 + (i / 7) * 12 + noise))
})
pts[pts.length - 1] = base
labels = ['7d', '6d', '5d', '4d', '3d', '2d', '1d', 'ahora']
}
const last = pts[pts.length - 1]
const col = last > 50 ? '#22d37a' : last < 40 ? '#f04040' : '#f0a020'
detailChartInstance = new Chart(ctx, {
type: 'line',
data: {
labels,
datasets: [
{
data: pts,
borderColor: col,
borderWidth: 1.5,
pointRadius: 0,
fill: false,
tension: 0.4,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: { legend: { display: false }, tooltip: { enabled: false } },
scales: { x: { display: false }, y: { display: false } },
animation: { duration: 600 },
},
})
}
export function renderSparkline(containerId, price, side) {
const el = document.getElementById(containerId)
if (!el) return
el.innerHTML = ''
el.className = 'sparkline'
const base = price * 100
for (let i = 0; i < 12; i++) {
const h = Math.max(4, Math.min(24, base / 4 + (Math.random() - 0.5) * 8))
const d = document.createElement('div')
d.className = 'spark-bar'
d.style.height = h + 'px'
d.style.background = side === 'yes' ? '#0d6e3a' : '#7a1a1a'
el.appendChild(d)
}
const last = document.createElement('div')
last.className = 'spark-bar'
last.style.height = Math.min(28, base / 3.5) + 'px'
last.style.background = side === 'yes' ? '#22d37a' : '#f04040'
el.appendChild(last)
}
|