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

如何在Canvas中绘制无抗锯齿文本,适配自定义复古等宽字体?

如何在Canvas中渲染无抗锯齿的像素风格文本

问题背景

需要在Canvas上显示无抗锯齿的固定等宽像素字体,现有实现中DOM元素可以渲染出清晰的像素边缘字体,但Canvas渲染的同字体文本存在抗锯齿模糊问题。

现有实现代码

<html>
    <head>
        <style type="text/css">
            @font-face {
                font-family: "AST";
                src: url(web_ast_premiumexec.woff) format('woff');
            }
            div {
                font-family: "AST";
                font-size: 16px;
            }
            canvas {
                font-smooth: never;
                -webkit-font-smoothing: none;
                /* image-rendering: pixelated; image-rendering: crisp-edges; */
            }
        </style>
    </head>
    <body>
        <div>А</div>
        <canvas id="canvas" width="32" height="32"></canvas>
        <script type="text/javascript">
            function setpixelated(context){
                context.imageSmoothingEnabled = false;       /* standard */
                context.mozImageSmoothingEnabled = false;    /* Firefox */
                context.oImageSmoothingEnabled = false;      /* Opera */
                context.webkitImageSmoothingEnabled = false; /* Safari */
                context.msImageSmoothingEnabled = false;     /* IE */
                context.imageSmoothingEnabled= false
            }
            var f = new FontFace('AST', 'url(web_ast_premiumexec.woff)');
            f.load().then(function() {
                const canvas = document.getElementById('canvas');
                const ctx = canvas.getContext('2d');
                setpixelated(ctx)
                ctx.font = "16px AST"
                ctx.fillstyle='#00f';
                ctx.filter = 'none';
                ctx.fillText('А', 0, 16);
            })
        </script>
    </body>
</html>

实际渲染效果

顶部为DOM渲染的清晰效果,底部为Canvas渲染的模糊效果:
输出效果


解决方案

按照以下步骤修改代码即可实现无抗锯齿的清晰像素文本:

  1. 修复代码笔误:将ctx.fillstyle改为驼峰命名ctx.fillStyle,错误的属性名会导致样式不生效。
  2. 放开Canvas样式中注释的渲染规则,明确指定像素级渲染:
canvas {
    font-smooth: never;
    -webkit-font-smoothing: none;
    image-rendering: pixelated;
    image-rendering: crisp-edges;
}
  1. 适配高分屏设备避免自动插值模糊:Canvas的实际画布尺寸需要乘以设备像素比,再通过CSS缩放到目标显示尺寸:
    修改JS逻辑如下:
f.load().then(function() {
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    // 适配高DPI屏幕
    const dpr = window.devicePixelRatio || 1;
    const displaySize = 32;
    canvas.width = displaySize * dpr;
    canvas.height = displaySize * dpr;
    canvas.style.width = `${displaySize}px`;
    canvas.style.height = `${displaySize}px`;
    ctx.scale(dpr, dpr);

    setpixelated(ctx);
    // 额外添加文本渲染优化规则
    ctx.textRendering = "optimizeSpeed";
    ctx.antialias = false;
    ctx.font = "16px AST";
    ctx.fillStyle = '#00f';
    ctx.filter = 'none';
    ctx.fillText('А', 0, 16);
})
  1. 如果部分浏览器依然存在抗锯齿,可以增加离屏Canvas二次绘制的逻辑:先把文本渲染到小尺寸离屏画布,再放大绘制到主画布,因为已经关闭了图像平滑,放大后会保留像素边缘不会模糊:
// 离屏渲染逻辑
const offscreen = document.createElement('canvas');
offscreen.width = 32;
offscreen.height = 32;
const offCtx = offscreen.getContext('2d');
setpixelated(offCtx);
offCtx.font = "16px AST";
offCtx.fillStyle = '#00f';
offCtx.fillText('А', 0, 16);
// 绘制到主画布
ctx.drawImage(offscreen, 0, 0, canvas.width, canvas.height);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 04:06:03