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

Canvas绘图:如何绘制不覆盖文本的二次曲线?

解决Canvas曲线与文本重叠的问题

针对你遇到的曲线和中心文本重叠的问题,这里提供两种实用的解决思路:

方法一:调整绘制层级(曲线在文本下方)

最简单的方式是改变绘制顺序,通过合成模式让曲线显示在文本下方,避免覆盖:

// 先绘制文本
const text = 'text on curve';
const textMeasurement = ctx.measureText(text);
const middlePoints = this._getControlPoints();
const textXPoint = middlePoints[0] - textMeasurement.width / 2;
ctx.fillText(text, textXPoint, middlePoints[1]);

// 设置合成模式,让后续绘制的内容显示在已有内容下方
ctx.globalCompositeOperation = 'destination-over';

// 绘制曲线
const startPoints = this._getStartPoints();
const endPoints = this._getEndPoints();
ctx.moveTo(...startPoints);
ctx.quadraticCurveTo(...this.getControlPoints(), ...endPoints);
ctx.stroke();

// 恢复默认合成模式
ctx.globalCompositeOperation = 'source-over';

方法二:拆分曲线绕开文本区域(曲线在文本两侧断开)

如果需要曲线完全避开文本区域,不穿过文本位置,可以计算文本的边界范围,将二次曲线拆分为两段绘制:

const text = 'text on curve';
const textMeasurement = ctx.measureText(text);
const middlePoints = this._getControlPoints();
const textXStart = middlePoints[0] - textMeasurement.width / 2;
const textXEnd = middlePoints[0] + textMeasurement.width / 2;
// 文本垂直范围(行高按字体大小1.2倍估算,可按需调整)
const fontSize = parseInt(ctx.font);
const textYRange = fontSize * 0.6;

// 定义文本两侧的曲线过渡点(可根据曲线形态微调位置)
const leftCurveEnd = [textXStart - 10, middlePoints[1]];
const rightCurveStart = [textXEnd + 10, middlePoints[1]];

// 绘制左侧曲线段
const startPoints = this._getStartPoints();
ctx.moveTo(...startPoints);
ctx.quadraticCurveTo(middlePoints[0], middlePoints[1], ...leftCurveEnd);
ctx.stroke();

// 绘制右侧曲线段
const endPoints = this._getEndPoints();
ctx.moveTo(...rightCurveStart);
ctx.quadraticCurveTo(middlePoints[0], middlePoints[1], ...endPoints);
ctx.stroke();

// 最后绘制文本
ctx.fillText(text, textXStart, middlePoints[1]);

说明:方法二中的过渡点可以根据你的实际曲线形态进一步优化,若需要更精准的路径,可通过数学方法求解二次曲线与文本边界矩形的交点坐标。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:55:26