Skip to content

标注

AnnotationManagement trait 提供了对标注(趋势线、形状、文本标签、斐波那契工具等)进行编程式增删改查的接口,适用于任意图表视图。ChartView 实现了此 trait,标注管理代码可与任意图表视图复用。

导入

rust
use navi_chart::{
    ChartView, AnnotationManagement, SystemAnnotationManagement,`n    AnnotationSpec, AnnotationFlags, AnnotationKind, AnnotationPane, ControlPoint,
    Stroke, Color, LineStyle, ExtendMode,
};

用法

rust
use navi_chart::{AnnotationManagement, AnnotationSpec, AnnotationId};

fn add_trend_line<C>(cv: &C, t1: i64, p1: f64, t2: i64, p2: f64) -> AnnotationId
where
    C: AnnotationManagement,
{
    cv.add_annotation(AnnotationSpec {
        kind: AnnotationKind::TrendLine {
            extend: ExtendMode::None,
            stroke: Stroke {
                color: Color::from_rgba(41, 98, 255, 255),
                width: 2.0,
                style: LineStyle::Solid,
            },
            text: String::new(),
        },
        points: vec![
            ControlPoint { time: t1, price: p1 },
            ControlPoint { time: t2, price: p2 },
        ],
        pane: AnnotationPane::Main,
        flags: AnnotationFlags::default(), // VISIBLE | SELECTABLE,未锁定
    })
}

// 两种视图类型均可使用:
let id = add_trend_line(&local_cv, t1, 150.0, t2, 165.0);
let id = add_trend_line(&remote_cv, t1, 150.0, t2, 165.0);

方法参考

方法说明
add_annotation(spec)添加新标注。立即重新渲染并推送 AnnotationCreated。返回稳定的非零 AnnotationId
update_annotation(id, spec)替换已有标注的完整 spec。重新渲染并推送 AnnotationUpdated
remove_annotation(id)按 id 移除标注。重新渲染并推送 AnnotationDeleted
clear_annotations()移除所有标注。为每个标注推送 AnnotationDeleted
annotation(id)按 id 返回标注引用,不存在则返回 None
annotations()按 Z 轴顺序(从后到前)返回所有标注。
annotation_properties(id)返回标注的属性描述符列表,已按图表当前语言本地化。可用于构建样式工具栏或属性面板。标注 id 不存在时返回 None
get_annotation_property(id, name)按路径名称读取单个属性(如 "stroke.color""stroke.width")。id 不存在则返回 None
set_annotation_property(id, name, value)写入单个属性。对 VIRTUAL 属性(如 ParallelChannel 上的 "colorAll"),写入会扇出到所有底层字段。立即重新渲染。id、属性名或值类型无效时返回 Err(ChartPropertyError)——详见下方错误说明。
delete_selected_annotation()删除当前选中的标注。无选中时为空操作。推送 AnnotationDeleted
bring_selected_annotation_to_front()将选中标注移至 Z 轴顶层。无选中时为空操作。
send_selected_annotation_to_back()将选中标注移至 Z 轴底层。无选中时为空操作。
toggle_selected_annotation_lock()切换选中标注的 locked 标志。已锁定的标注不能被用户移动或编辑。无选中时为空操作。
copy_selected_annotation()将选中标注复制到图表内部剪贴板。无选中时为空操作。
cut_selected_annotation()将选中标注复制到剪贴板后删除它。无选中时为空操作。
paste_annotation()将剪贴板中的标注粘贴为新标注(位置略有偏移)。推送 AnnotationCreated。剪贴板为空时为空操作。
has_clipboard_annotation()剪贴板中存在已复制的标注则返回 true
selected_annotation_bounds()返回选中标注在画布像素坐标中的边界框,可用于定位浮动工具栏。无选中时返回 None
selected_annotation_is_highlighter()选中标注为 Highlighter 笔刷时返回 true,可据此显示高亮专属工具栏。
dispatch_context_menu_action(action)对选中标注执行上下文菜单操作字符串(如 "delete""lock""bring-to-front""send-to-back""copy""cut""paste")。在用户从 context_menu_items(pos) 填充的菜单中选择项目后调用。
annotation_control_point_flags(id)按顺序返回标注 id 每个控制点的 ControlPointFlags,不存在时返回 None。构建坐标编辑 Tab 时,可根据这些标志确定哪些坐标轴被锁定。
set_annotation_default(tool_id, kind)为指定绘图工具保存每工具样式默认值。下次通过绘图流程创建该工具的标注时,将使用这些属性而非出厂默认值。
reset_annotation_to_default(id)将标注的样式属性重置为出厂默认值,并清除该工具已保存的每工具默认值。推送 AnnotationUpdated 并重新渲染。

关于选择相关方法的说明

delete_selected_annotationbring_selected_annotation_to_frontsend_selected_annotation_to_backtoggle_selected_annotation_lockcopy_selected_annotationcut_selected_annotationselected_annotation_bounds 均作用于当前选中的标注。无选中时均为空操作,可从工具栏按钮中无条件调用。

set_annotation_property 的错误情况

set_annotation_property 在以下情况返回 Err(ChartPropertyError)

  • 标注 id 不存在。
  • 该标注类型不存在该属性名称。
  • 值的类型与属性类型不匹配。

示例:属性工具栏

rust
use navi_chart::{AnnotationManagement, ChartInteraction, PropertyValue, Color};

fn apply_color_from_toolbar<C>(cv: &C, color: Color)
where
    C: AnnotationManagement + ChartInteraction,
{
    if let Some(ChartElement::Annotation(id)) = cv.selection() {
        // 优先尝试虚拟属性(扇出到所有描边)
        let _ = cv.set_annotation_property(id, "colorAll", PropertyValue::Color(color))
            .or_else(|_| cv.set_annotation_property(id, "stroke.color", PropertyValue::Color(color)));
    }
}

示例:持久化往返

rust
use navi_chart::{AnnotationManagement, Annotation, AnnotationSpec};

fn save_annotations<C>(cv: &C) -> String
where
    C: AnnotationManagement,
{
    let annotations: Vec<Annotation> = cv.annotations();
    serde_json::to_string(&annotations).unwrap()
}

fn restore_annotations<C>(cv: &C, json: &str)
where
    C: AnnotationManagement,
{
    let saved: Vec<Annotation> = serde_json::from_str(json).unwrap();
    cv.clear_annotations();
    for ann in saved {
        cv.add_annotation(ann.spec);
    }
}

ControlPointFlags

annotation_control_point_flags(id) 按顺序返回标注每个控制点的 ControlPointFlags。构建坐标编辑 Tab 时,可根据这些标志确定哪些轴向输入框需要隐藏。

标志位值含义
LOCK_BAR_INDEX0b0001该点的 X 轴(柱索引/时间)固定,隐藏柱索引输入框。
LOCK_PRICE0b0010该点的 Y 轴(价格)固定,隐藏价格输入框。
FOLLOW_FIRST_BAR_INDEX0b0100绘制时,该点继承第一个控制点的 X 值。
FOLLOW_FIRST_PRICE0b1000绘制时,该点继承第一个控制点的 Y 值。
rust
use navi_chart::{AnnotationManagement, annotation::ControlPointFlags};

fn build_coordinates_tab<C: AnnotationManagement>(cv: &C, id: AnnotationId) {
    let annotation = cv.annotation(id).unwrap();
    let flags_per_point = cv.annotation_control_point_flags(id).unwrap_or_default();

    for (i, point) in annotation.spec.points.iter().enumerate() {
        let flags = flags_per_point.get(i).copied().unwrap_or_default();

        if !flags.contains(ControlPointFlags::LOCK_BAR_INDEX) {
            render_bar_index_input(i, point.time);
        }
        if !flags.contains(ControlPointFlags::LOCK_PRICE) {
            render_price_input(i, point.price);
        }
    }
}

AnnotationKind 变体完整列表、AnnotationSpec 结构、PropertyDescriptor 字段和样式子结构的详细说明,请参阅 ChartView

基于 MIT 许可证发布。