函数 _drawSingleSuspenseEvent 用于在 Canvas 上绘制单个 React Suspense 事件。它接收一个 CanvasRenderingContext2D 对象、一个矩形 rect、一个 SuspenseEvent 对象以及其他参数,并在 Canvas 上绘制相应的悬挂事件。

函数执行过程如下:

  1. 根据事件的深度调整基准垂直位置 baseY
  2. 根据事件的警告状态和分辨率设置填充颜色 fillStyle
  3. 根据事件的时间戳和持续时间计算事件的起始和结束位置 xStartxStop
  4. 如果事件是一个未解决的挂起事件(即没有持续时间),则绘制一个菱形,否则绘制一个矩形。
  5. 如果事件在给定的矩形范围内可见,则绘制事件的形状和颜色。
  6. 计算事件形状在给定矩形范围内的可见部分的矩形,并在该矩形内部绘制事件的标签。

以下是代码的详细说明:

_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 来绘制事件形状,并使用其他辅助函数来计算事件位置、持续时间和标签内容。它使用不同的颜色来表示不同的事件状态,例如 resolvedrejectedunresolved。最终,该函数在 Canvas 上绘制一个清晰且信息丰富的悬挂事件可视化。

React Suspense 事件可视化:绘制单个悬挂事件

原文地址: https://www.cveoy.top/t/topic/qm59 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录