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

HTML canvas实现线矢量左右两侧绘制不同宽度单侧线条方案咨询

Canvas单侧扩展线条实现方案

核心原理

Canvas默认绘制线条时,lineWidth会沿路径两侧各扩展lineWidth/2的宽度。要实现仅单侧扩展,只需将原始路径沿非扩展侧的法线方向偏移lineWidth/2的距离后再绘制即可。

通用实现(支持任意角度线段)

偏移量计算逻辑

沿线段起点走向终点的方向,区分左右侧偏移:

  1. 计算线段方向向量:dx = 终点x - 起点x,dy = 终点y - 起点y
  2. 计算线段长度:len = Math.sqrt(dx*dx + dy*dy)
  3. 左侧单位法向量:nx = -dy/len,ny = dx/len
  4. 右侧单位法向量:nx = dy/len,ny = -dx/len
  5. 偏移后的坐标 = 原始坐标 + 法向量 * (线宽/2)

完整代码示例

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

/**
 * 绘制单侧扩展线段
 * @param {number} x1 原始线段起点x坐标
 * @param {number} y1 原始线段起点y坐标
 * @param {number} x2 原始线段终点x坐标
 * @param {number} y2 原始线段终点y坐标
 * @param {number} lineWidth 线条宽度
 * @param {'left'|'right'} side 扩展方向(沿线段走向的左侧/右侧)
 * @param {string} color 线条颜色
 */
function drawSingleSideLine(x1, y1, x2, y2, lineWidth, side, color) {
  const dx = x2 - x1;
  const dy = y2 - y1;
  const len = Math.sqrt(dx * dx + dy * dy);
  
  // 计算对应方向的单位法向量
  const [nx, ny] = side === 'left' 
    ? [-dy / len, dx / len]
    : [dy / len, -dx / len];
  
  // 计算偏移后的坐标
  const offset = lineWidth / 2;
  const offsetX1 = x1 + nx * offset;
  const offsetY1 = y1 + ny * offset;
  const offsetX2 = x2 + nx * offset;
  const offsetY2 = y2 + ny * offset;

  // 绘制线条
  ctx.lineWidth = lineWidth;
  ctx.strokeStyle = color;
  ctx.beginPath();
  ctx.moveTo(offsetX1, offsetY1);
  ctx.lineTo(offsetX2, offsetY2);
  ctx.stroke();
}

// 测试用例:同一路径左侧画8px红色线,右侧画4px蓝色线
drawSingleSideLine(100, 100, 400, 200, 8, 'left', '#ff0000');
drawSingleSideLine(100, 100, 400, 200, 4, 'right', '#0000ff');

简化场景(水平/垂直线)

如果仅需要绘制水平或垂直线,可直接跳过向量计算,按方向直接偏移:

  • 水平向右的线段:左侧扩展就将y坐标减lineWidth/2,右侧扩展就将y坐标加lineWidth/2
  • 垂直向下的线段:左侧扩展就将x坐标加lineWidth/2,右侧扩展就将x坐标减lineWidth/2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:06:02