185 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { reactive, ref } from "vue";
import { time2cursorX, SystemPivot } from "./cursor";
import { globalLookup } from "@/hook/global";
import formatTime from "@/hook/wave-view/format-time";
import { RelativeAxis } from './relative-axis';
/**
* @description 每一个动态信标
* @typedef {Object} UserPivot
* @property {number} id
* @property {string} label
* @property {number} x
* @property {number} time
* @property {boolean} show
*/
/**
* @description 该数据结构描述了所有通过 makePivot 创建的 用户信标
* @type {Map<number, UserPivot>} number 为当前信标在数轴中的刻度
*/
export const UserPivots = reactive(new Map());
/**
* @type {Map<number, UserPivot>} number 为 idid 是创建的 Unix 时间戳
*/
export const Id2Pivot = reactive(new Map());
/**
* @description 应该被渲染到当前屏幕中的
* @type {Set<number>}
*/
export const VisibleUserPivotIds = reactive(new Set());
export const orderedTimes = [];
export const UserPivotColor = ref('#1e90ff');
/**
* @description 创建一个信标
* @param {number} time 需要创建的轴的时间点
*/
export function createPivot(time) {
if (UserPivots.has(time)) {
return;
}
const id = Date.now();
const x = time2cursorX(time);
const timescale = globalLookup.timescale;
const label = formatTime(time, timescale);
const show = true;
const pivot = { time, x, id, label, show };
UserPivots.set(time, pivot);
Id2Pivot.set(id, pivot);
orderedTimes.push(time);
orderedTimes.sort((a, b) => a < b);
}
export function searchOrderedTimeIndex(time) {
for (let i = 0; i < orderedTimes.length; ++ i) {
if (orderedTimes[i] === time) {
return i;
}
}
return undefined;
}
export function deletePivot(time) {
if (!UserPivots.has(time)) {
return;
}
const i = searchOrderedTimeIndex(time);
if (i !== undefined) {
orderedTimes.splice(i, 1);
}
if (UserPivots.has(time)) {
const pivot = UserPivots.get(time);
UserPivots.delete(time);
Id2Pivot.delete(pivot.id);
UserPivotCtxShows.delete(pivot.id);
// 如果当前的删除的信标刚好是相对坐标轴的,那么把相对坐标轴也隐藏
if (RelativeAxis.show && RelativeAxis.currentPivotId === pivot.id) {
RelativeAxis.show = false;
currentPivotId.value = 0;
}
}
currentPivotId.value = 0;
}
export const boxShift = 25;
export function updateAllPivots() {
// 更新系统信标
SystemPivot.updateLeft();
// 维护可见 Pivots
VisibleUserPivotIds.clear();
// 更新所有用户信标
for (const time of UserPivots.keys()) {
const pivot = UserPivots.get(time);
const x = time2cursorX(time);
const cx = x - boxShift; // 25 是 boxShift也就是展示数字圆形的一半宽度
if (cx > 0 && cx < (globalLookup.pstate.width || window.innerWidth)) {
VisibleUserPivotIds.add(pivot.id);
}
pivot.x = x;
}
}
/**
*
* @param {number[]} times
* @param {number} target 目标时间
* @returns
*/
function bisearch(times, target) {
let i = 0, j = times.length - 1;
while (i < j) {
if (times[i] === target) {
break;
}
if (times[j] <= target) {
i = j;
break;
}
if (j - i === 1) {
break;
}
const mid = (i + j) >> 1;
if (times[mid] > target) {
j = mid;
} else {
i = mid;
}
}
return i;
}
/**
* @description 高效获取距离 time 最近的时间点 t时间复杂度 O(logn)
* @param {number} time
* @returns {UserPivot | undefined}
*/
export function getNearestUserPivot(time) {
const pivotNum = UserPivots.size;
if (pivotNum === 0) {
return undefined;
}
if (pivotNum === 1) {
for (const [time, pivot] of UserPivots) {
return pivot;
}
}
const i = bisearch(orderedTimes, time);
// console.log(i, orderedTimes, time);
if (i === pivotNum - 1) {
return UserPivots.get(orderedTimes[i]);
}
const prevT = orderedTimes[i];
const nextT = orderedTimes[i + 1];
if (nextT - time > time - prevT) {
return UserPivots.get(prevT);
}
return UserPivots.get(nextT);
}
/**
* @type {Map<number, boolean>}
*/
export const UserPivotCtxShows = reactive(new Map());
export const currentPivotId = ref(0);