| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 |
- /**
- * 浮动面板锚点:合并集合并按规则吸附到合法 height(无 Vue 依赖,便于测试与复用)。
- */
- export type AnchorsSnapResult = { anchors: number[]; height: number };
- /**
- * 根据新锚点候选合并列表,并计算吸附后的 `height`。
- * @param values - 本次写入的锚点(或单个)
- * @param reset - 为 `true` 时以 `values` 为基底;为 `false` 时与 `currentAnchors` 合并
- * @param prevHeight - 吸附前的面板总高度
- * @param maxContainerHeight - 允许的最大总高度(px)
- * @param currentAnchors - 当前 v-model 锚点(`reset === false` 时参与合并)
- */
- export function computeAnchorsAndSnapHeight(
- values: number | number[],
- reset: boolean,
- prevHeight: number,
- maxContainerHeight: number,
- currentAnchors: readonly number[],
- ): AnchorsSnapResult | null {
- const list = !Array.isArray(values) ? [values] : values;
- const set = new Set(list);
- if (!reset) currentAnchors.forEach((a) => set.add(a));
- const anchors = [...set].filter((v) => v <= maxContainerHeight).sort((a, b) => a - b);
- if (!anchors.length) return null;
- const hit = anchors.findIndex((v) => v === prevHeight);
- if (hit >= 0) {
- return { anchors, height: anchors[hit]! };
- }
- let nearest = anchors[0]!;
- let minDist = Math.abs(prevHeight - nearest);
- for (const a of anchors) {
- const d = Math.abs(prevHeight - a);
- if (d < minDist) {
- minDist = d;
- nearest = a;
- }
- }
- const positives = anchors.filter((a) => a > 0);
- if (nearest === 0 && prevHeight > 0 && positives.length) {
- const height = positives.reduce((m, a) => (Math.abs(a - prevHeight) < Math.abs(m - prevHeight) ? a : m));
- return { anchors, height };
- }
- return { anchors, height: nearest };
- }
|