add graph cursor

This commit is contained in:
2025-01-04 11:45:09 -05:00
parent 35603c98a4
commit c69022448f
5 changed files with 139 additions and 39 deletions

View File

@@ -21,6 +21,7 @@ const props = defineProps<{
hide_time_ticks?: boolean;
include_controls?: boolean;
legend?: GraphSide;
cursor?: boolean;
}>();
const divRef = useTemplateRef<HTMLDivElement>('graph-div');
@@ -109,15 +110,23 @@ const border_bottom = computed(() => (props.hide_time_labels ? 6 : 24));
const max_x = now;
const min_x = computed(() => max_x.value - window_duration.value);
const diff_x = computed(() => max_x.value - min_x.value);
const x_map = (x: number) => {
const diff_x = max_x.value - min_x.value;
return (
((width.value - border_left.value - border_right.value) *
(x - min_x.value)) /
diff_x +
diff_x.value +
border_left.value
);
};
const inv_x_map = (x: number) => {
return (
((x - border_left.value) * diff_x.value) /
(width.value - border_left.value - border_right.value) +
min_x.value
);
};
const telemetry_lines = ref([]);
@@ -132,25 +141,6 @@ const legend_x_stride = computed(() => 0);
const legend_y_stride = computed(() => 16);
const legend_width_output = computed(() => legend_width - 8);
provide<GraphData>(GRAPH_DATA, {
border_top: border_top,
min_x: min_x,
max_x: now,
width: () =>
Math.max(width.value - border_left.value - border_right.value, 0),
height: () =>
Math.max(height.value - border_top.value - border_bottom.value, 0),
x_map: x_map,
lines: telemetry_lines,
max_update_rate: 1000 / 10,
legend_enabled: legend_enabled,
legend_x: legend_x,
legend_y: legend_y,
legend_x_stride: legend_x_stride,
legend_y_stride: legend_y_stride,
legend_width: legend_width_output,
});
const line_duration = computed(() => {
const diff_x = max_x.value - min_x.value;
return time_lines.find((duration) => diff_x / duration >= 2)!;
@@ -168,6 +158,65 @@ const lines = computed(() => {
}
return result;
});
const mouse_x = ref<number | null>(null);
function onMouseMove(event: MouseEvent) {
if (props.cursor) {
const new_x =
event.clientX -
(event.currentTarget as Element).getBoundingClientRect().left;
if (new_x == 0) {
console.log(event);
}
mouse_x.value = new_x;
}
}
function onMouseOut() {
mouse_x.value = null;
}
const mouse_t = computed(() => {
if (mouse_x.value === null) {
return null;
}
const t = inv_x_map(mouse_x.value);
if (t < min_x.value || t > max_x.value) {
// console.log(`x ${mouse_x.value} t ${t} min ${t < min_x.value} max ${t > max_x.value}`)
// debugger;
return null;
}
return t;
});
const show_data_at_time = computed(() => {
if (mouse_t.value === null) {
return max_x.value;
} else {
return mouse_t.value;
}
});
provide<GraphData>(GRAPH_DATA, {
border_top: border_top,
min_x: min_x,
max_x: now,
width: () =>
Math.max(width.value - border_left.value - border_right.value, 0),
height: () =>
Math.max(height.value - border_top.value - border_bottom.value, 0),
x_map: x_map,
lines: telemetry_lines,
max_update_rate: 1000 / 10,
legend_enabled: legend_enabled,
legend_x: legend_x,
legend_y: legend_y,
legend_x_stride: legend_x_stride,
legend_y_stride: legend_y_stride,
legend_width: legend_width_output,
cursor_time: show_data_at_time,
});
</script>
<template>
@@ -182,7 +231,14 @@ const lines = computed(() => {
<span>Duration Dropdown</span>
</div>
</div>
<svg ref="svg_graph" class="graph" :width="width" :height="height">
<svg
ref="svg_graph"
class="graph"
:width="width"
:height="height"
@mousemove="onMouseMove"
@mouseleave="onMouseOut"
>
<defs>
<clipPath id="content">
<rect
@@ -231,6 +287,27 @@ const lines = computed(() => {
</template>
</g>
<slot></slot>
<g class="cursor_tick" v-if="mouse_t && cursor">
<rect
:x="x_map(mouse_t) - 100"
:y="height - border_bottom"
width="200"
height="20"
></rect>
<polyline
:points="`${x_map(mouse_t)},${border_top} ${x_map(mouse_t)},${height - border_bottom}`"
></polyline>
<TimeText
v-if="mouse_t"
id="cursor_text"
class="bottom_edge"
:x="x_map(mouse_t)"
:y="height - border_bottom + text_offset"
:timestamp="mouse_t"
:utc="props.utc"
show_millis
></TimeText>
</g>
</svg>
</div>
</template>
@@ -249,6 +326,16 @@ const lines = computed(() => {
fill: variables.$time-tick;
}
.cursor_tick {
stroke: variables.$cursor-tick;
fill: variables.$cursor-tick;
}
.cursor_tick > rect {
fill: variables.$background-color;
opacity: 66%;
}
div.full-size {
width: 100%;
height: 100%;