React Suspense 事件可视化:绘制单个悬挂事件
函数 _drawSingleSuspenseEvent 用于在 Canvas 上绘制单个 React Suspense 事件。它接收一个 CanvasRenderingContext2D 对象、一个矩形 rect、一个 SuspenseEvent 对象以及其他参数,并在 Canvas 上绘制相应的悬挂事件。
函数执行过程如下:
- 根据事件的深度调整基准垂直位置
baseY。 - 根据事件的警告状态和分辨率设置填充颜色
fillStyle。 - 根据事件的时间戳和持续时间计算事件的起始和结束位置
xStart和xStop。 - 如果事件是一个未解决的挂起事件(即没有持续时间),则绘制一个菱形,否则绘制一个矩形。
- 如果事件在给定的矩形范围内可见,则绘制事件的形状和颜色。
- 计算事件形状在给定矩形范围内的可见部分的矩形,并在该矩形内部绘制事件的标签。
以下是代码的详细说明:
_drawSingleSuspenseEvent(
context: CanvasRenderingContext2D,
rect: Rect,
event: SuspenseEvent,
baseY: number,
scaleFactor: number,
showHoverHighlight: boolean,
) {
const { frame } = this;
const {
componentName,
depth,
duration,
phase,
promiseName,
resolution,
timestamp,
warning,
} = event;
baseY += depth * ROW_WITH_BORDER_HEIGHT;
let fillStyle = ((null: any): string);
if (warning !== null) {
fillStyle = showHoverHighlight
? COLORS.WARNING_BACKGROUND_HOVER
: COLORS.WARNING_BACKGROUND;
} else {
switch (resolution) {
case 'rejected':
fillStyle = showHoverHighlight
? COLORS.REACT_SUSPENSE_REJECTED_EVENT_HOVER
: COLORS.REACT_SUSPENSE_REJECTED_EVENT;
break;
case 'resolved':
fillStyle = showHoverHighlight
? COLORS.REACT_SUSPENSE_RESOLVED_EVENT_HOVER
: COLORS.REACT_SUSPENSE_RESOLVED_EVENT;
break;
case 'unresolved':
fillStyle = showHoverHighlight
? COLORS.REACT_SUSPENSE_UNRESOLVED_EVENT_HOVER
: COLORS.REACT_SUSPENSE_UNRESOLVED_EVENT;
break;
}
}
const xStart = timestampToPosition(timestamp, scaleFactor, frame);
// Pending suspense events (ones that never resolved) won't have durations.
// So instead we draw them as diamonds.
if (duration === null) {
const size = PENDING_SUSPENSE_EVENT_SIZE;
const halfSize = size / 2;
baseY += (SUSPENSE_EVENT_HEIGHT - PENDING_SUSPENSE_EVENT_SIZE) / 2;
const y = baseY + halfSize;
const suspenseRect: Rect = {
origin: {
x: xStart - halfSize,
y: baseY,
},
size: { width: size, height: size },
};
if (!rectIntersectsRect(suspenseRect, rect)) {
return; // Not in view
}
context.beginPath();
context.fillStyle = fillStyle;
context.moveTo(xStart, y - halfSize);
context.lineTo(xStart + halfSize, y);
context.lineTo(xStart, y + halfSize);
context.lineTo(xStart - halfSize, y);
context.fill();
} else {
const xStop = timestampToPosition(
timestamp + duration,
scaleFactor,
frame,
);
const eventRect: Rect = {
origin: {
x: xStart,
y: baseY,
},
size: { width: xStop - xStart, height: SUSPENSE_EVENT_HEIGHT },
};
if (!rectIntersectsRect(eventRect, rect)) {
return; // Not in view
}
const width = durationToWidth(duration, scaleFactor);
if (width < 1) {
return; // Too small to render at this zoom level
}
const drawableRect = intersectionOfRects(eventRect, rect);
context.beginPath();
context.fillStyle = fillStyle;
context.fillRect(
drawableRect.origin.x,
drawableRect.origin.y,
drawableRect.size.width,
drawableRect.size.height,
);
let label = 'suspended';
if (promiseName != null) {
label = promiseName;
} else if (componentName != null) {
label = `${componentName} ${label}`;
}
if (phase !== null) {
label += ` during ${phase}`;
}
if (resolution !== 'unresolved') {
label += ` - ${formatDuration(duration)}`;
}
drawText(label, context, eventRect, drawableRect);
}
}
该函数使用 Canvas API 来绘制事件形状,并使用其他辅助函数来计算事件位置、持续时间和标签内容。它使用不同的颜色来表示不同的事件状态,例如 resolved、rejected 和 unresolved。最终,该函数在 Canvas 上绘制一个清晰且信息丰富的悬挂事件可视化。
原文地址: https://www.cveoy.top/t/topic/qm59 著作权归作者所有。请勿转载和采集!