插件
为图表扩展自定义指标、画线工具、 图表类型和叠加层——可以全局注册,也可以按图表注册。
注册
共有三种注册方式,按优先级顺序依次为:全局默认、构造函数,以及在实例上以命令式调用。
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() 插件种类
| 种类 | 契约 | 渲染位置 |
|---|---|---|
indicator | IndicatorPlugin — calculate() + render() | 主图叠加或副图 |
drawing | DrawingPlugin — render() + hitTest() | 叠加图层 |
chartType | ChartTypePlugin — createRenderer() + 可选的 transform() | 主序列 |
overlay | OverlayPlugin — 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 每一帧都在你选择的图层上绘制,并接收实时的视口、数据和主题:
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) 按图表自身的方式定位:timeToX / xToTime 按 K 线时间(两根 K 线之间及最新 K 线之后按比例), indexToX / xToIndex,priceToY / yToPrice(对数坐标与反转坐标同样适用), barWidth,以及屏幕上可见的 K 线范围 visible。要按价格网格划分行,用 chart.getPriceStep():
品种的最小变动价位(minTick)、分数单位,或当前显示小数位的一个单位。指标和图表类型的渲染器只拿到 viewport,
为此导出了 priceToY、barIndexToX、timeToX 及其反函数。这里的 K 线是屏幕上绘制的序列:
在 Renko 或 Kagi 图上就是它的砖块(chart.isTimeAligned() 表示它们是否就是数据源的 K 线)。
带有自身设置(显示模式、开关)的叠加层可以立即显示变化,即使没有新的 tick 触发重绘:在插件上设置 enabled: false 可在保持注册的同时隐藏它;修改设置或开关后调用 chart.requestRender()。
下一帧之前的多次请求只绘制一帧。
完整的插件类型签名请参见 API 参考。