You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Canvas组件渲染时字体加载失败问题求助

解决React Canvas组件字体加载延迟问题

问题说明

React Canvas组件首次渲染时,指定的Great Vibes、Ubuntu等字体未完成加载,导致Canvas文本默认显示系统字体(如Comic Sans),仅刷新页面后才会显示目标字体。已尝试Font Face构造器、CSS配置、本地字体导入、Google Fonts链接等方案,均未解决。

核心原因

组件挂载后立即执行Canvas绘制逻辑,但此时字体文件尚未加载完成,Canvas API会自动回退到系统默认字体;刷新页面时字体已被浏览器缓存,因此能正常显示。

解决方案

通过FontFace API手动管理字体加载流程,确保所有目标字体加载完成后再执行Canvas绘制操作:

1. 封装字体加载函数

在组件内部创建加载所需字体的异步函数,使用Promise.all等待所有字体加载完成:

const loadFonts = async () => {
  // 加载Great Vibes字体(本地文件示例,根据实际路径调整)
  const greatVibes = new FontFace(
    'Great Vibes',
    'url("../fonts/GreatVibes-Regular.woff2") format("woff2")'
  );
  // 加载Ubuntu字体
  const ubuntu = new FontFace(
    'Ubuntu',
    'url("../fonts/Ubuntu-Regular.woff2") format("woff2")'
  );

  // 添加字体到文档
  await greatVibes.load();
  document.fonts.add(greatVibes);
  
  await ubuntu.load();
  document.fonts.add(ubuntu);

  // 等待字体在文档中完全可用
  await document.fonts.ready;
};

2. 控制Canvas绘制时机

新增状态标记字体加载状态,修改useEffect逻辑,仅在字体加载完成后执行绘制:

import React, { useEffect, useRef, useState, useCallback } from "react";
// ... 保留其他导入 ...

const Canvas = ({ height, width, imageUrl, courseId }) => {
  const canvasRef = useRef(null);
  const { userId, userName } = useParams();
  const [fontsLoaded, setFontsLoaded] = useState(false); // 标记字体加载完成

  // 用useCallback包裹draw函数,避免频繁重建
  const draw = useCallback((context) => {
    // ... 保留原draw函数所有内容 ...
  }, [courseId, userId, userName]);

  const loadFonts = async () => {
    // 上述字体加载代码
    await document.fonts.ready;
    setFontsLoaded(true);
  };

  useEffect(() => {
    loadFonts();
  }, []);

  useEffect(() => {
    if (!fontsLoaded) return; // 字体未加载完成时跳过绘制

    const canvas = canvasRef.current;
    const context = canvas.getContext("2d");
    const image = new Image();

    image.onload = () => {
      context.drawImage(image, 0, 0, width, height);
      draw(context);
    };
    image.src = imageUrl;
  }, [draw, height, width, imageUrl, fontsLoaded]); // 添加fontsLoaded依赖

  // ... 保留原return部分 ...
};

3. 额外优化点

  • 确保字体路径正确:本地字体文件建议放在public/fonts目录下,使用绝对路径(如"/fonts/GreatVibes-Regular.woff2")避免路径解析错误
  • 若使用Google Fonts,可在loadFonts函数中通过document.fonts.check()验证字体是否加载完成,替代本地文件加载逻辑

内容的提问来源于stack exchange,提问作者wolfie00

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:54:58