圖表視圖
navi-chart crate 提供 ChartView<P, T> — 一個圖表元件,管理多個 Navi 指標、處理用戶交互,並透過平台無關的繪圖介面渲染。Provider P 決定腳本如何執行及資料來自何處。
LocalChartProvider | 自訂 ChartProvider | |
|---|---|---|
| 腳本執行 | 本地 — 在進程內執行 VM | 遠端 — 後端串流推送事件 |
| Provider trait | ChartProvider(Script = String) | ChartProvider(Script = 自訂類型) |
| 依賴 | 需要 local feature(引入 navi-vm) | 無 VM 依賴 — 預設即可用 |
| 適用場景 | 桌面應用、CLI 工具、Playground | Web 前端、伺服器端執行 |
Cargo Features
[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。 |
spawn、interval、now_ms 三個方法必須實作,其餘均有預設值。
參考實作: Web Playground 的
WebPlatform使用wasm_bindgen_futures::spawn_local、setInterval、js_sys::Date::now()。
DrawingContext
為你的渲染平台(Canvas 2D、Skia、Cairo 等)實作 DrawingContext trait。所有座標和尺寸均為邏輯/CSS 像素。
參考實作: 參見 Web Playground 使用的 Canvas 2D 後端。
畫布
| 方法 | 作用 |
|---|---|
clear() | 將所有像素清除為完全透明(或平台背景色)。每幀開始時呼叫一次。 |
顏色與樣式
這些方法設定持久狀態,作用於後續的繪製呼叫。
| 方法 | 作用 |
|---|---|
set_fill_color(color) | 將填充畫筆設定為純 RGBA 顏色,用於 fill、fill_rect、fill_text 之前。 |
set_stroke_color(color) | 將描邊畫筆設定為純 RGBA 顏色,用於 stroke、stroke_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 像素。formatting 為 TextFormatting::Normal、Bold 或 Italic。family 為 FontFamily::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 | 返回當前字型的垂直度量(ascent 和 descent,以字母基線為基準,單位像素),用於精確的多行文字排版。預設實作返回零;能查詢真實字型度量的後端應覆寫此方法。Canvas 2D 後端應呼叫 measureText("M") 並讀取 fontBoundingBoxAscent / fontBoundingBoxDescent。 |
路徑
路徑透過 begin_path / move_to / line_to / close_path / arc / arc_to 構建,再由 stroke 或 fill 繪製,與標準 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() 取出。事件僅攜帶 ScriptId 或 AnnotationId;在釋放借用後再呼叫輔助方法查詢關聯資料。
| 事件 | 說明 |
|---|---|
EditScript(ScriptId) | 用戶點擊了指標圖例上的 ✎ 編輯按鈕 |
RemoveScript(ScriptId) | 用戶點擊了 ✕ 移除按鈕 |
ShowError(ScriptId) | 用戶點擊了 ⚠ 錯誤圖示 — 呼叫 cv.script_error(id) 獲取錯誤訊息 |
ConfigureScript(ScriptId) | 用戶點擊了 ⚙ 配置按鈕 — 呼叫 cv.script_inputs_effective(id) 獲取輸入項 |
DoubleClick(ChartElement) | 用戶雙擊了系列圖形或 K 線柱 |
SelectionChanged(Option<ChartElement>) | 選中元素發生變化或被清除。ChartElement 為 Bar(usize)、Series { script_id, graph_id } 或 Annotation(AnnotationId) 之一 |
AnnotationCreated(AnnotationId) | 新注釋被新增 — 來自用戶完成繪圖手勢,或直接呼叫 add_annotation |
AnnotationUpdated(AnnotationId) | 注釋規格透過 update_annotation 被替換 |
AnnotationDeleted(AnnotationId) | 注釋透過 remove_annotation、clear_annotations 或用戶按下 Delete 鍵被刪除 |
// 每次交互方法呼叫後,輪詢並處理待處理事件:
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 管理腳本的視覺覆寫和輸入值覆寫:
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 均在子頁面中說明: