InfoRadar / client /src /ts /controllers /highlightController.ts
dqy08's picture
统一可视化配置,并将信息密度单位从字符改为字节
e9c9e16
import * as d3 from 'd3';
import type { GLTR_Text_Box } from '../vis/GLTR_Text_Box';
import type { Histogram } from '../vis/Histogram';
import type { HistogramBinClickEvent } from '../vis/Histogram';
import type { FrontendAnalyzeResult } from '../api/GLTR_API';
import { calculateHighlights } from '../utils/highlightUtils';
export type HighlightControllerOptions = {
stats_frac: Histogram;
lmf: GLTR_Text_Box;
currentData: { result: FrontendAnalyzeResult } | null;
};
export class HighlightController {
private options: HighlightControllerOptions;
constructor(options: HighlightControllerOptions) {
this.options = options;
}
/**
* 清除所有高亮(文本与直方图)
*/
public clearHighlights(): void {
this.options.stats_frac.clearSelection();
this.options.lmf.clearHighlight();
}
/**
* 处理直方图 bin 点击事件
*/
public handleHistogramBinClick(ev: HistogramBinClickEvent): void {
const { currentData } = this.options;
if (!currentData) return;
// 如果 binIndex 为 -1,表示用户取消选择,清除所有高亮
if (ev.binIndex === -1) {
this.clearHighlights();
return;
}
const { x0, x1, binIndex, no_bins, source } = ev;
const data = currentData.result;
// 仅处理 token 直方图
const { indices, style } = calculateHighlights('token', x0, x1, binIndex, no_bins, data);
// 高亮这些 token
this.options.lmf.setHighlightedIndices(indices, style);
}
/**
* 更新当前数据(当数据变化时调用)
*/
public updateCurrentData(currentData: { result: FrontendAnalyzeResult } | null): void {
// 创建一个新对象来更新,保持 options 对象的引用不变
(this.options as any).currentData = currentData;
}
}
/**
* 初始化高亮清除事件监听(点击空白处和 ESC 键)
*/
export const initHighlightClearListeners = (
clearHighlights: () => void
): void => {
// 点击页面空白处清除高亮(通用解决方案)
// 监听整个文档的点击事件,但排除可交互元素
d3.select('body').on('click.clearHighlight', (event: MouseEvent) => {
const target = <HTMLElement>event.target;
if (!target) return;
// 排除可交互元素:token、按钮、输入框、直方图bin等
const isInteractive =
target.closest('.token') || // token元素
target.closest('button') || // 按钮
target.closest('input') || // 输入框
target.closest('textarea') || // 文本域
target.closest('select') || // 下拉框
target.closest('.bar') || // 直方图bar
target.closest('.hover-area') || // 直方图悬停区域
target.closest('a') || // 链接
target.closest('[role="button"]') || // 有button角色的元素
target.closest('[onclick]'); // 有onclick属性的元素
// 如果点击的不是可交互元素,则清除高亮
if (!isInteractive) {
clearHighlights();
}
});
// 按下 ESC 键清除高亮
d3.select(window).on('keydown.clearHighlight', (event: KeyboardEvent) => {
if (event.key === 'Escape') {
clearHighlights();
}
});
};