Plugins
Amplía el gráfico con indicadores, herramientas de dibujo, tipos de gráfico y capas personalizados, registrados de forma global o por gráfico.
Registro
Hay tres formas de registrar, por orden de prioridad: valores globales por defecto, el constructor y, por último, llamadas imperativas sobre la instancia.
import { Chart, registerPlugin } from '@tradecanvas/chart'
// 1) Global — every Chart created afterward inherits it
registerPlugin({ kind: 'indicator', plugin: new MyIndicator() })
// 2) Per-chart at construction
const chart = new Chart(el, { plugins: [{ kind: 'overlay', plugin: myHeatmap }] })
// 3) Imperative on an instance
chart.plugins.register({ kind: 'chartType', plugin: myCandles })
chart.plugins.unregister('chartType:my-candles')
chart.plugins.list() Tipos de plugin
| Tipo | Contrato | Dónde se dibuja |
|---|---|---|
indicator | IndicatorPlugin — calculate() + render() | superpuesto o en panel |
drawing | DrawingPlugin — render() + hitTest() | capa superpuesta |
chartType | ChartTypePlugin — createRenderer() + transform() opcional | serie principal |
overlay | OverlayPlugin — render(ctx, { viewport, data, theme }) | main / overlay / ui |
Indicador personalizado
Extiende IndicatorBase para usar sus utilidades de dibujo; después regístralo y añádelo como cualquier indicador integrado:
import { IndicatorBase, IndicatorValueMap, registerPlugin } from '@tradecanvas/chart'
class DoubleSMA extends IndicatorBase {
descriptor = {
id: 'double-sma', name: 'Double SMA',
placement: 'overlay', defaultConfig: { fast: 10, slow: 30 },
}
calculate(data, config) { /* values = new IndicatorValueMap(); return { values, series } */ }
render(ctx, output, viewport, style) { /* draw lines */ }
}
registerPlugin({ kind: 'indicator', plugin: new DoubleSMA() })
chart.addIndicator('double-sma', { fast: 10, slow: 30 }) Para values, usa new IndicatorValueMap() en lugar de new Map(): es un Map intercambiable que resulta varias
veces más barato de llenar barra a barra en orden temporal, que es justo lo que
hace cada cambio de símbolo o de temporalidad sobre todo el historial.
Actualizaciones rápidas en vivo (opcional)
En cada tick en vivo solo cambia la barra en formación. Implementa update() para recalcular solo las barras a partir de from en lugar de todo el historial: el gráfico lo usa con los ticks
y las barras nuevas, y recurre a calculate() cuando no existe o
devuelve null. Debe producir los mismos valores que produciría calculate().
update(data, config, prev, from) {
if (!this.canResume(data, prev, from)) return null // IndicatorBase helper
for (let i = from; i < data.length; i++) {
this.writePoint(prev, data, i, { value: /* recompute bar i */ 0 })
}
return prev
} Herramienta de dibujo personalizada
Extiende DrawingBase para usar sus utilidades (de anclas a píxeles,
estilos de línea, puntos de control), describe la herramienta y regístrala. La
configuración que enumeres en descriptor.options aparece en el
diálogo de configuración del widget y se guarda con el dibujo.
import { DrawingBase, registerPlugin } from '@tradecanvas/chart'
class TargetLine extends DrawingBase {
descriptor = {
type: 'targetLine', name: 'Target Line', requiredAnchors: 1,
options: { label: { kind: 'text', label: 'Label', default: 'Target' } },
}
render(ctx, state, viewport, selected) { /* en this.anchorToPixel(state.anchors[0], viewport) */ }
hitTest(point, state, viewport, tolerance) { /* ¿está el puntero sobre él? */ return false }
// opcional: los precios de sus líneas, para que una alerta pueda seguirlas
priceAt(state) { return [state.anchors[0].price] }
}
registerPlugin({ kind: 'drawing', plugin: new TargetLine() })
chart.setDrawingTool('targetLine') El descriptor también puede indicar cómo se dibuja la herramienta
(creation: 'clicks', 'freehand' o 'path', con maxAnchors) y si el diálogo ofrece un
relleno (fill) o texto (text). Una herramienta puede
mover puntos de control que no son anclas con moveHandle() y
recibe las barras del gráfico mediante setDataGetter() cuando
dibuja a partir de ellas.
Tipo de gráfico personalizado
Un ChartTypePlugin aporta un renderizador y una transformación de datos opcional; cámbiate a él como a uno integrado:
registerPlugin({
kind: 'chartType',
plugin: {
descriptor: { type: 'my-bricks', name: 'My Bricks' },
createRenderer: () => new MyBrickRenderer(),
transform: (raw) => toBricks(raw), // optional
},
})
chart.setChartType('my-bricks') Capa personalizada
Un OverlayPlugin dibuja cada fotograma en la capa que elijas y recibe la vista, los datos y el tema actuales:
import { overlayScale, registerPlugin } from '@tradecanvas/chart'
registerPlugin({
kind: 'overlay',
plugin: {
descriptor: { id: 'high-marks', name: 'High marks', layer: 'main' },
render(ctx, context) {
const s = overlayScale(context)
ctx.fillStyle = '#f2a93b'
for (let i = s.visible.from; i <= s.visible.to; i++) {
const bar = context.data[i]
ctx.fillRect(s.indexToX(i) - s.barWidth / 2, s.priceToY(bar.high) - 1, s.barWidth, 2)
}
},
},
}) overlayScale(context) coloca las cosas donde las dibuja el gráfico: timeToX / xToTime por la hora de la vela (entre velas y más allá de la última, en proporción), indexToX / xToIndex, priceToY / yToPrice (también en escala logarítmica o invertida), barWidth y visible, las velas en pantalla. Para filas en la cuadrícula de precios, chart.getPriceStep() es el
paso mínimo del símbolo (minTick), la unidad de una fracción o una unidad de los decimales que se muestran.
Los renderizadores de indicadores y tipos de gráfico solo reciben el viewport: para ellos se exportan priceToY, barIndexToX, timeToX y sus inversas. Las velas son las que están en
pantalla: en un gráfico Renko o Kagi, sus ladrillos (chart.isTimeAligned() indica cuándo son las velas del feed).
Un overlay con ajustes propios (un modo de visualización, un interruptor) puede mostrar un cambio al instante,
aunque no llegue ningún tick que redibuje el gráfico: pon enabled: false en el plugin para ocultarlo
sin quitar su registro, y llama a chart.requestRender() tras cambiar cualquiera de los dos. Varias
peticiones antes del siguiente fotograma dibujan uno solo.
Consulta la referencia de la API para ver las firmas de tipos completas de los plugins.