ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

gpui-kit Slider 原语实战:状态驱动的范围输入组件架构与实现

gpui-kit Slider 原语实战:状态驱动的范围输入组件架构与实现 gpui-kit Slider 原语实战状态驱动的范围输入组件架构与实现【免费下载链接】gpui-kitRust GUI components for building fantastic cross-platform desktop application by using GPUI.项目地址: https://gitcode.com/GitHub_Trending/gp/gpui-kitSlider 是 gpui-kit 中gpui-base提供的状态驱动范围输入原语轨道Track、已选区Indicator和滑块Thumb可独立设置样式行为与语义结构由基础类型负责。本文以 Slider 中文文档 为核心骨架结合 源码 与 示例实现讲解如何用它在 GPUI 中构建符合自己设计系统的滑杆控件。核心设计思想行为与表现分离与gpui-base中的所有原语一致Slider 只提供行为和语义结构不规定产品视觉语言状态SliderState持久保存值、范围、步进与当前交互状态结构Slider/SliderTrack/SliderIndicator/SliderThumb是无样式行为根节点负责把指针位置映射为值表现由消费方用 GPUI 样式Styled、事件 traitInteractiveElement等组合这些部件实现。这种分层使同一份行为代码可以承载任意视觉主题也保证了原生与 WASM 预览编译的是同一份实现。运行示例原生示例与页面上方的 WASM 预览共用同一份实现运行命令cargo run -p gpui-base-examples -- slider该命令通过 crates/base/examples/showcase/mod.rs 中的共享 showcase 初始化应用、创建窗口并提供BaseShowcase状态命令选择逻辑见 mod.rs。导入use gpui_kit::base::{Slider, SliderState};gpui_kit::base是对gpui_basecrate 的重导出见 crates/kit/src/lib.rsSliderState、Slider、SliderTrack、SliderIndicator、SliderThumb均通过 crates/base/src/lib.rs 的pub use对外公开。权威示例实现位于 crates/base/examples/showcase/components/slider.rs。结构与 API示例组合以下公开类型GPUI 的标准样式与事件 trait 负责表现Base 类型负责交互结构类型职责Slider行为根节点声明role: Slider并暴露 ARIA 数值属性提供水平/垂直方向与禁用能力SliderTrack无样式轨道记录几何信息以将指针位置映射为值处理轨道点击与整条拖动SliderIndicator已选区指示器通过on_prepaint记录用于值映射的 boundsSliderThumb可拖动的滑块支持start标记以区分范围模式下的起始/结束把手SliderState状态实体持久保存值、范围、步进、百分比位置、bounds 与拖动标志这些类型都在 crates/base/src/slider.rs 中定义。状态与事件SliderState是EventEmitterSliderEvent见 slider.rs持久的gpui::EntitySliderState在示例中通过cx.new(|_| SliderState::new().min(0.).max(100.).default_value(64.))创建见 showcase/mod.rs并通过cx.observe在状态变化时触发重绘。SliderEvent提供两种事件slider.rsChange(SliderValue)拖动或点击过程中连续发出Release(SliderValue)用户松开滑块后发出一次。受控状态应保存在父渲染类型或 GPUI entity 中在回调中更新并调用cx.notify()不要在每次渲染时重建持久 entity。完整 Rust 示例权威实现原生与浏览器预览编译同一文件位于 crates/base/examples/showcase/components/slider.rs核心组合如下let percentage self.slider.read(cx).percentage().end; let thumb_size 14.; div() .w_56() .text_xs() .child(div().mb_2().flex().justify_between() .child(Volume).child(Drag to adjust)) .child( Slider::new(self.slider).w_full().h_7().child( SliderTrack::new(self.slider) .relative().w_full().h_full() .child(div().absolute().top(px(13.)).left_0().w_full() .h(px(2.)).bg(super::example_rgb(0xd4d4d4))) // 轨道 .child( SliderIndicator::new(self.slider) .absolute().top(px(13.)).left_0().w_full().h(px(2.)) .child(div().absolute().top_0().bottom_0().left_0() .right(relative(1. - percentage)) .bg(super::example_rgb(0x171717))), // 已选区 ) .child( SliderThumb::new(self.slider) .absolute().top(px(7.)).left(relative(percentage)) .ml(px(-thumb_size / 2.)) .size(px(thumb_size)) .bg(super::example_rgb(0xffffff)) .border_1().border_color(super::example_rgb(0x171717)), // 滑块 ), ), )状态构建与观察showcase/mod.rs 演示了状态生命周期let slider cx.new(|_| SliderState::new().min(0.).max(100.).default_value(64.)); cx.observe(slider, |_, _, cx| cx.notify()).detach();状态模型与刻度SliderValue与SliderScaleSliderValue支持单值与范围两种形态slider.rsSliderValue::Single(f32)单值SliderValue::Range(f32, f32)范围双滑块。支持从f32、(f32, f32)元组和Rangef32转换默认值为SliderValue::Single(0.0)。提供start()/end()/clamp()/is_range()等方法其中set_start保证start endset_end保证end startslider.rs。SliderState的默认配置min 0.0、max 100.0、step 1.0、刻度Linearslider.rs。线性刻度值均匀分布在范围上value min (max - min) * percentageslider.rs。对数刻度SliderScale::Logarithmic适用于音量人耳听觉近似对数、频率音符、缩放级别等低值处需要更精细控制的参数slider.rslet slider SliderState::new() .min(1.0) // 对数刻度下必须 0 .max(1000.0) .scale(SliderScale::Logarithmic);映射公式为base.powf(percentage) * minbase max / min。在 1..1000 范围内滑块移动 1/3 处约得 ~102/3 处约得 ~100整个范围均匀覆盖 3 个数量级。约束对数模式下min 0且min max否则在min()/max()/scale()中直接assert!失败slider.rs。指针交互与事件流轨道点击含范围模式选边SliderTrack在鼠标按下时若为范围模式先根据点击位置与已选区中心的比较决定拖动起始把手还是结束把手position center则拖 start再调用update_value_by_positionslider.rs。整条拖动单值模式下SliderTrack注册on_dragon_drag_move把轨道本身作为拖动目标DragSlider拖动过程中持续更新值slider.rs。滑块拖动SliderThumb在on_mouse_down中stop_propagation阻止事件冒泡到轨道然后用DragThumb((entity_id, start))启动自身拖动on_drag_move中根据start标记更新起始或结束把手slider.rs。值映射与步进update_value_by_positionslider.rs依据方向取指针相对 bounds 的位置水平用position.x - bounds.left()垂直用bounds.bottom() - position.y归一化为 0..1 的百分比范围模式下按把手边界 clamp经percentage_to_value反算值并做步进取整(value / step).round() * step更新内部百分比与值cx.emit(SliderEvent::Change(...))并cx.notify()。释放事件Slider在on_mouse_up与on_mouse_up_out都监听slider.rshandle_release仅在用户确实按过/拖过dragging true时才发出一次SliderEvent::Releaseslider.rs。这保证 Release 只在真实交互后出现。方向与禁用Slider::new(state)默认水平可用.horizontal()/.vertical()/.axis(Axis)指定方向slider.rsSlider、SliderTrack、SliderThumb均提供.disabled(bool)。禁用后不注册鼠标事件但 ARIA 属性与结构仍渲染slider.rs。可访问性Slider渲染时声明Role::Slider并暴露aria_numeric_value当前值取value().end()、aria_min_numeric_value、aria_max_numeric_value、aria_numeric_value_step与aria_orientationslider.rs同时注册AccessibleAction::Increment/Decrement无障碍动作按步进在范围内增减slider.rs并保留方向键、Page Up/Down 等键盘操作能力。测试验证crates/base/src/slider.rs 中的单元测试覆盖了关键行为SliderValue的三种转换与clamp如Range(-1., 12.).clamp(0., 10.) Range(0., 10.)线性状态下的百分比映射与范围排序min 0 / max 200 / 默认 (50, 150)→ 百分比0.25..0.75对数刻度映射min 1 / max 1000 / 值 10→ 百分比端值 ≈ 1/3对数校验scale(SliderScale::Logarithmic)且min 0时 panic。注意事项在支持的位置使用稳定元素 ID示例中如slider-bar-container、slider-bar、slider-thumb见 slider.rs并在消费端设计系统中验证焦点、悬停、按下、选中、禁用、减少动态效果和高对比度状态。相关主题可进一步参考 基础原语文档 与 Slider 组件层文档。【免费下载链接】gpui-kitRust GUI components for building fantastic cross-platform desktop application by using GPUI.项目地址: https://gitcode.com/GitHub_Trending/gp/gpui-kit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表