Skip to content

圖表視圖

navi-chart crate 提供 ChartView<P, T> — 一個圖表元件,管理多個 Navi 指標、處理用戶交互,並透過平台無關的繪圖介面渲染。Provider P 決定腳本如何執行及資料來自何處。

LocalChartProvider自訂 ChartProvider
腳本執行本地 — 在進程內執行 VM遠端 — 後端串流推送事件
Provider traitChartProvider(Script = String)ChartProvider(Script = 自訂類型)
依賴需要 local feature(引入 navi-vm無 VM 依賴 — 預設即可用
適用場景桌面應用、CLI 工具、PlaygroundWeb 前端、伺服器端執行

Cargo Features

toml
[dependencies]
# 僅遠端/自訂 Provider(無 VM):
navi-chart = { git = "https://github.com/longbridge/navi.git" }

# 使用 LocalChartProvider(進程內 VM):
navi-chart = { git = "https://github.com/longbridge/navi.git", features = ["local"] }
Feature啟用內容
(預設 — 無)ChartView + ChartProvider trait,無 VM。
local新增 LocalChartProvider,引入 navi-vm

共享概念

兩種用法共享相同的渲染、交互和配置 API。

Platform

Platform trait 將圖表引擎與宿主執行環境解耦。構建 ChartView 時傳入實作——引擎透過它排程非同步任務、計時器、取得當前時間及存取剪貼板。

方法預設值說明
spawn(fut)在宿主執行環境以 fire-and-forget 方式生成 future。
interval(interval_ms)interval_ms 毫秒產出一次 () 的計時器。返回 IntervalStream;drop 時自動取消(RAII)。
now_ms()返回當前時間(毫秒)。紀元由宿主定義,引擎只使用差值。
double_click_threshold_ms()500.0兩次點擊被識別為雙擊的最大間隔(毫秒)。可覆寫以讀取系統偏好。
write_clipboard(text)空操作非同步寫入系統剪貼板。
read_clipboard()None非同步讀取系統剪貼板。拒絕存取或為空時返回 None

spawnintervalnow_ms 三個方法必須實作,其餘均有預設值。

參考實作: Web Playground 的 WebPlatform 使用 wasm_bindgen_futures::spawn_localsetIntervaljs_sys::Date::now()

DrawingContext

為你的渲染平台(Canvas 2D、Skia、Cairo 等)實作 DrawingContext trait。所有座標和尺寸均為邏輯/CSS 像素。

參考實作: 參見 Web Playground 使用的 Canvas 2D 後端

畫布

方法作用
clear()將所有像素清除為完全透明(或平台背景色)。每幀開始時呼叫一次。

顏色與樣式

這些方法設定持久狀態,作用於後續的繪製呼叫。

方法作用
set_fill_color(color)將填充畫筆設定為純 RGBA 顏色,用於 fillfill_rectfill_text 之前。
set_stroke_color(color)將描邊畫筆設定為純 RGBA 顏色,用於 strokestroke_rect 之前。
set_line_width(width)設定描邊線寬(像素)。
set_line_dash(pattern)設定虛線樣式,參數為交替的繪製/間隔長度(如 &[6.0, 3.0] = 6 px 實線、3 px 間隔)。傳空切片恢復實線。
set_fill_linear_gradient(x0,y0,x1,y1,stops)將填充畫筆設定為從 (x0,y0)(x1,y1) 的線性漸層。stops(offset, Color) 列表,offset ∈ [0.0, 1.0]。

文字

方法作用
set_font(size, formatting, family)設定當前字型。size 為 CSS 像素。formattingTextFormatting::NormalBoldItalicfamilyFontFamily::Default(無襯線)或 FontFamily::Monospace
set_text_align(align)設定相對於 fill_text 傳入 x 座標的水平對齊方式:Left = x 為左邊緣,Center = x 為中點,Right = x 為右邊緣。
set_text_baseline(baseline)設定相對於 fill_text 傳入 y 座標的垂直基線:Top = em 框頂部,Middle = 垂直居中,Bottom = 底部,Alphabetic = 標準字母基線。
fill_text(text, x, y)使用當前字型、填充顏色、對齊方式和基線,在像素位置 (x, y) 繪製文字。
measure_text(text) -> f64使用當前字型設定返回 text 的渲染寬度(像素)。必須精確 — 圖表用於標籤排版和重疊偵測。
font_metrics() -> FontMetrics返回當前字型的垂直度量(ascentdescent,以字母基線為基準,單位像素),用於精確的多行文字排版。預設實作返回零;能查詢真實字型度量的後端應覆寫此方法。Canvas 2D 後端應呼叫 measureText("M") 並讀取 fontBoundingBoxAscent / fontBoundingBoxDescent

路徑

路徑透過 begin_path / move_to / line_to / close_path / arc / arc_to 構建,再由 strokefill 繪製,與標準 Canvas 2D 路徑模型一致。

方法作用
begin_path()丟棄已有路徑,開始新的空路徑。
move_to(x, y)將當前點移動到 (x, y) 而不繪製任何內容,開始新子路徑。
line_to(x, y)從當前點到 (x, y) 追加直線段,並更新當前點。
close_path()從當前點到當前子路徑起點追加直線,然後閉合路徑。
arc(x, y, radius)追加以 (x, y) 為圓心、給定半徑的完整圓(0 到 2π)。
arc_to(x1,y1,x2,y2,radius)追加由兩條切線(當前點 → (x1,y1)(x1,y1)(x2,y2))定義的圓弧,等同於 Canvas 2D arcTo,用於圓角。
stroke()用當前描邊顏色和線寬繪製路徑描邊。
fill()用當前填充畫筆(顏色或漸層)填充路徑內部。

形狀

無需手動構建路徑的便捷方法。

方法作用
fill_rect(rect)用當前填充畫筆填充矩形 rect。等同於 begin_path + rect + fill
stroke_rect(rect)用當前描邊顏色和線寬繪製矩形 rect 的輪廓。

裁剪(可選)

方法作用
set_clip(rect)Some(rect) 將後續所有繪製限制在給定矩形內。第二次呼叫 set_clip(Some(other))取代前一個裁剪區域(不做交集)。None 移除裁剪並恢復無限制繪製。預設實作為空操作 — 如後端支援裁剪請覆寫。Canvas 2D 後端應在內部使用 save/clip/restore

ChartEvent

交互事件在圖表視圖內部積累,每次交互呼叫後透過 poll_event() 取出。事件僅攜帶 ScriptIdAnnotationId;在釋放借用後再呼叫輔助方法查詢關聯資料。

事件說明
EditScript(ScriptId)用戶點擊了指標圖例上的 ✎ 編輯按鈕
RemoveScript(ScriptId)用戶點擊了 ✕ 移除按鈕
ShowError(ScriptId)用戶點擊了 ⚠ 錯誤圖示 — 呼叫 cv.script_error(id) 獲取錯誤訊息
ConfigureScript(ScriptId)用戶點擊了 ⚙ 配置按鈕 — 呼叫 cv.script_inputs_effective(id) 獲取輸入項
DoubleClick(ChartElement)用戶雙擊了系列圖形或 K 線柱
SelectionChanged(Option<ChartElement>)選中元素發生變化或被清除。ChartElementBar(usize)Series { script_id, graph_id }Annotation(AnnotationId) 之一
AnnotationCreated(AnnotationId)新注釋被新增 — 來自用戶完成繪圖手勢,或直接呼叫 add_annotation
AnnotationUpdated(AnnotationId)注釋規格透過 update_annotation 被替換
AnnotationDeleted(AnnotationId)注釋透過 remove_annotationclear_annotations 或用戶按下 Delete 鍵被刪除
rust
// 每次交互方法呼叫後,輪詢並處理待處理事件:
cv.on_mouse_up(pos);
while let Some(event) = cv.poll_event() {
    match event {
        ChartEvent::EditScript(id) => { /* 開啟編輯器 */ }
        ChartEvent::RemoveScript(id) => { /* 確認並移除 */ }
        ChartEvent::ShowError(id) => {
            let error = cv.script_error(id).unwrap();
            // 顯示錯誤訊息
        }
        ChartEvent::ConfigureScript(id) => {
            let inputs = cv.script_inputs_effective(id).unwrap();
            // 開啟配置對話框
        }
        ChartEvent::DoubleClick(element) => { /* 處理 */ }
        ChartEvent::SelectionChanged(sel) => { /* 處理 */ }
        ChartEvent::AnnotationCreated(id) => { /* 持久化新注釋 */ }
        ChartEvent::AnnotationUpdated(id) => { /* 更新已持久化的注釋 */ }
        ChartEvent::AnnotationDeleted(id) => { /* 從持久化中刪除 */ }
        _ => {}
    }
}

ToggleVisibility 由內部處理 — 圖表會自動切換可見性並重新渲染。

ScriptConfig

ScriptConfig 管理腳本的視覺覆寫和輸入值覆寫:

rust
pub struct ScriptConfig {
    /// 每個系列圖形的視覺覆寫(顏色、樣式、可見性)。
    pub series_overrides: HashMap<SeriesGraphId, SeriesGraphOverride>,
    /// 輸入值覆寫。Key = 輸入項索引,value = JSON 值。
    pub input_values: HashMap<usize, serde_json::Value>,
}

完整的配置 UI 指南見 ChartView 頁面。

ScriptId

ScriptId 是新增腳本時返回的不透明識別碼,用於查詢、配置或移除腳本。

渲染與交互

所有渲染和交互 API 均在子頁面中說明:

  • 腳本管理 — 新增、移除、查詢腳本
  • 交互 — 滑鼠、滾輪、拖曳、光標、選擇
  • 注釋 — CRUD、屬性、選擇、剪貼簿
  • 繪圖工具 — 工具狀態機、粘性模式、磁吸
  • 視口 — 面板比例、捲動、縮放、高亮 bar
  • 設定與事件 — 主題、語言、品種/時間週期、策略報告、poll_event

基於 MIT 許可證發佈。