Plugin

Mở rộng biểu đồ bằng chỉ báo, công cụ vẽ, loại biểu đồ và lớp phủ tuỳ chỉnh — đăng ký toàn cục hoặc cho từng biểu đồ.

Đăng ký

Có ba cách đăng ký, theo thứ tự ưu tiên: mặc định toàn cục, qua constructor, rồi gọi trực tiếp trên instance.

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

Các loại plugin

LoạiInterfaceVẽ ở
indicatorIndicatorPlugin — calculate() + render()phủ lên biểu đồ hoặc bảng riêng
drawingDrawingPlugin — render() + hitTest()lớp overlay
chartTypeChartTypePlugin — createRenderer() + transform() tuỳ chọnchuỗi chính
overlayOverlayPlugin — render(ctx, { viewport, data, theme })main / overlay / ui

Chỉ báo tuỳ chỉnh

Kế thừa IndicatorBase để có sẵn các hàm hỗ trợ vẽ, rồi đăng ký và thêm nó như mọi chỉ báo có sẵn:

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

Với values, hãy dùng new IndicatorValueMap() thay vì new Map(): nó thay thế trực tiếp được cho Map nhưng rẻ hơn nhiều lần khi điền từng nến theo thứ tự thời gian, đúng là việc mà mỗi lần đổi mã hay khung thời gian phải làm trên toàn bộ lịch sử.

Cập nhật trực tiếp nhanh (tuỳ chọn)

Mỗi tick trực tiếp chỉ làm thay đổi nến đang hình thành. Cài đặt update() để chỉ tính lại các nến từ from trở đi thay vì toàn bộ lịch sử — biểu đồ dùng nó khi có tick và nến mới, và quay về calculate() khi hàm này không có hoặc trả về null. Nó phải cho ra đúng các giá trị mà calculate() sẽ cho.

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
}

Công cụ vẽ tuỳ chỉnh

Kế thừa DrawingBase để có sẵn các hàm hỗ trợ (đổi điểm neo ra pixel, kiểu nét, điểm kéo), mô tả công cụ rồi đăng ký nó. Các cài đặt liệt kê trong descriptor.options sẽ hiện trong hộp thoại cài đặt của widget và được lưu cùng hình vẽ.

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) { /* tại this.anchorToPixel(state.anchors[0], viewport) */ }
  hitTest(point, state, viewport, tolerance) { /* con trỏ có nằm trên nó không? */ return false }
  // tuỳ chọn: giá của các đường, để cảnh báo có thể bám theo
  priceAt(state) { return [state.anchors[0].price] }
}

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

Descriptor còn có thể cho biết công cụ được vẽ ra sao (creation: 'clicks', 'freehand' hoặc 'path', kèm maxAnchors) và hộp thoại có cho chọn màu nền (fill) hay chữ (text) hay không. Công cụ có thể di chuyển các điểm kéo không phải điểm neo bằng moveHandle(), và nhận các nến của biểu đồ qua setDataGetter() khi nó vẽ dựa trên chúng.

Loại biểu đồ tuỳ chỉnh

Một ChartTypePlugin cung cấp bộ render và một phép biến đổi dữ liệu tuỳ chọn; chuyển sang nó như với một loại có sẵn:

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

chart.setChartType('my-bricks')

Lớp phủ tuỳ chỉnh

Một OverlayPlugin vẽ mỗi khung hình trên lớp bạn chọn, nhận khung nhìn, dữ liệu và giao diện (theme) hiện tại:

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

Xem Tham chiếu API để biết đầy đủ chữ ký kiểu của plugin.