插件

为图表扩展自定义指标、画线工具、 图表类型和叠加层——可以全局注册,也可以按图表注册。

注册

共有三种注册方式,按优先级顺序依次为:全局默认、构造函数,以及在实例上以命令式调用。

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()

插件种类

种类契约渲染位置
indicatorIndicatorPlugin — calculate() + render()主图叠加或副图
drawingDrawingPlugin — render() + hitTest()叠加图层
chartTypeChartTypePlugin — createRenderer() + 可选的 transform()主序列
overlayOverlayPlugin — render(ctx, { viewport, data, theme })main / overlay / ui

自定义指标

继承 IndicatorBase 以获得绘图辅助方法,然后像内置指标一样注册并添加:

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 })

values 请使用 new IndicatorValueMap() 而不是 new Map():它可以直接替代 Map,在按时间顺序逐根K线写入时开销要低好几倍——而每次切换品种或周期时, 都会对整段历史数据执行这样的写入。

快速实时更新(可选)

每次实时 tick 只有正在形成的K线会变化。实现 update(),只重新计算从 from 开始的K线,而不是整段历史——图表会在收到 tick 和新K线时使用它; 如果未实现或返回 null,则回退到 calculate()。 它产生的数值必须与 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
}

自定义画线工具

继承 DrawingBase 以使用它的辅助方法(锚点转像素、线型、控制点),再描述该工具并注册。 descriptor.options 中列出的设置会出现在组件的设置对话框里,并随画线一起保存。

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) { /* 在 this.anchorToPixel(state.anchors[0], viewport) 处 */ }
  hitTest(point, state, viewport, tolerance) { /* 指针是否在它上面? */ return false }
  // 可选:各条线的价格,便于提醒跟随它们
  priceAt(state) { return [state.anchors[0].price] }
}

registerPlugin({ kind: 'drawing', plugin: new TargetLine() })
chart.setDrawingTool('targetLine')

描述对象还可以说明工具的绘制方式(creation: 'clicks'、'freehand' 或 'path',并可配合 maxAnchors),以及对话框是否提供填充(fill)或文本 (text)。工具可以用 moveHandle() 移动不属于锚点的控制点; 如果绘制时需要用到图表的K线,则通过 setDataGetter() 获取。

自定义图表类型

ChartTypePlugin 提供一个渲染器和一个可选的数据变换;切换方式与内置类型相同:

registerPlugin({
  kind: 'chartType',
  plugin: {
    descriptor: { type: 'my-bricks', name: 'My Bricks' },
    createRenderer: () => new MyBrickRenderer(),
    transform: (raw) => toBricks(raw),   // optional
  },
})

chart.setChartType('my-bricks')

自定义叠加层

OverlayPlugin 每一帧都在你选择的图层上绘制,并接收实时的视口、数据和主题:

registerPlugin({
  kind: 'overlay',
  plugin: {
    descriptor: { id: 'vwap-band', name: 'VWAP Band', layer: 'main' },
    render(ctx, { viewport, data, theme }) {
      // draw onto the main layer with the current viewport + data
    },
  },
})

完整的插件类型签名请参见 API 参考。