tactile-motion
v0.1.0
Published
A headless motion engine for tactile UI controls.
Maintainers
Readme
tactile-motion
面向触感交互控件的无头运动引擎。
适用于标尺(Ruler)、滑块(Slider)、选择器(Picker)、旋钮(Knob)、时间轴及 Canvas 控件。
手势层输入 → 物理演算 → 数值输出
drag → velocity → inertia → settle- 连续运动:基于指数衰减的精确物理模型,手感细腻可调。
- 零依赖:Core 核心零运行时依赖(压缩后约 1.8 kB gzip)。
- 无头设计(Headless):不绑定 DOM 事件与渲染层,自由配合任何 UI。
- 框架无关:纯 TS 核心库,附带开箱即用的 React 适配器。
- 帧率无关:在 30 / 60 / 120 / 144 Hz 下具有一致的物理落点。
安装
npm install tactile-motion若使用 React 适配器(tactile-motion/react),需在宿主项目中安装 react(>= 16.8.0)。
核心使用(Core API)
import { createTactileMotion } from 'tactile-motion';
const motion = createTactileMotion({
value: 0,
min: 0,
max: 1000,
friction: 0.94,
velocityMultiplier: 1,
maxVelocity: 3,
threshold: 0.01,
onChange(value) {
render(value);
},
onStateChange(state) {
console.log(state); // 'idle' | 'dragging' | 'animating'
},
onRest(value) {
console.log('settled', value);
},
});
// 绑定手势生命周期:
motion.start(); // 手指按下 / 拖拽开始
motion.drag(12.5); // 移动,传入单次增量 delta
motion.release(); // 松手,启动惯性滑动
motion.stop(); // 立即停止并保持当前位置
motion.set(500); // 停止并直接定位到指定值配置项(Options)
| 参数 | 默认值 | 说明 |
| -------------------- | ------------------------ | -------------------------------------------------------------------- |
| value | 0 | 初始数值(会自动受限于 [min, max])。 |
| min / max | -Infinity / Infinity | 硬边界范围。 |
| friction | 0.94 | 每 16.67ms 保留的速度比例(0 <= friction < 1),数值越小减速越快。 |
| velocityMultiplier | 1 | 释放时的速度放大倍率。 |
| maxVelocity | Infinity | 释放速度上限(单位/ms),在倍率生效后截断。 |
| threshold | 0.01 | 静止速度阈值(单位/ms),低于此值触发停止。 |
| scheduler | RAF / timer | 帧调度器适配层。 |
实例方法(Methods)
| 方法 | 说明 |
| --------------------- | --------------------------------------------------------- |
| getValue() | 获取当前数值。 |
| getSnapshot() | 获取不可变的快照对象 { value, velocity, state }。 |
| start(time?) | 进入 dragging 状态并重置速度采样。 |
| drag(delta, time?) | 应用位移增量并更新速度估算。 |
| release(time?) | 释放拖拽并进入 animating 惯性阶段(无速度时直接静止)。 |
| stop() | 取消运动并在当前数值停留在 idle 状态。 |
| set(value) | 取消运动,直接设置受限数值并通知变更。 |
| configure(options) | 动态更新配置项。 |
| subscribe(listener) | 监听快照变更,返回取消订阅函数。 |
React
import { useTactileMotion } from 'tactile-motion/react';
function Slider() {
const motion = useTactileMotion({
min: 0,
max: 100,
maxVelocity: 2,
onChange(val) {
// 变动回调
},
});
return (
<div>
<span>{motion.value.toFixed(1)}</span>
{/* 手势层可调用 motion.dragStart() / motion.dragMove(delta) / motion.dragEnd() */}
</div>
);
}Hook 返回当前快照属性(value, velocity, state)、全部核心方法,以及便捷别名 dragStart、dragMove、dragEnd。原生支持 SSR 与 React StrictMode。
刻度吸附(Snapping)
引擎本身专注连续物理运动。吸附逻辑应由控件语义层在 onRest 中决定:
const step = 10;
const motion = createTactileMotion({
onRest(position) {
motion.set(Math.round(position / step) * step);
},
});本地开发
# 启动示例实验台(Ruler、Slider、Knob、Canvas)
npm install
npm run dev
# 运行全套检查与测试
npm run checkLicense
MIT
