图片标注编辑平台搭建系列教程(5)——线宽不居中问题

背景

fabric中的polyline和polygon(继承自polyline),有一个普遍问题,就是如果设置了left和top后,同时设置了线宽,会发现线宽并不是沿着坐标序列居中渲染,而是以坐标最小外接矩形的左上角为原点,整体往右和下渲染。本期从源码内容详细分析成因。

现象

fabric中有一个选中框的概念,有几个控制的锚点,途中的矩形是500px,同时线宽20,从右下角绿色点(500,500)的位置可以看出,这个选中框的宽度=500+20=520,即width+strokeWidth。

如果画一条(0,0)到(500,500)的线,在不添加left和top的情况下,如左图,可以看到线的中心线是符合要求的。但如果你添加了left=0,top=0,那么渲染效果如右图。可以看出,线的端点有一定的偏移,具体来看,整体偏移了strokeWidth/2。

如果是(0,0)到(0,500)的线,在不设置left和top的效果如左图,设置left=0,top=0是,效果如右图。

原因

造成上述的原因是:在polyline的初始化方法中,调用了_setPositionDimensions方法,该方法中对于left和top没有赋值的情况,源代码自身进行了赋值(calcDim.left - strokeWidth / 2);一旦你设置了left和top,就会采用你设置的left和top,从而导致渲染上的偏移。(注意,这里的偏移程度取决于strokeWidth,对于线而言,strokeWidth的设置不可避免,因此只要设置了left和top多少都会有一定的偏移)。

由于每个object的ctx原点是基于ctx transform后,再一次进行偏移到object中心点,其偏移量为:

javascript 复制代码
x = this.left + 0.5 * (width + strokeWidth) = calcDim.left + 0.5 * width
y = this.top + 0.5 * (height + strokeWidth) = calcDim.top + 0.5 * height

在this.left 赋值的情况下,偏移量为:

javascript 复制代码
x = this.left + 0.5 * (width + strokeWidth) = calcDim.left + 0.5 * (width + strokeWidth);
y = this.top + 0.5 * (height + strokeWidth) = calcDim.top + 0.5 * (height + strokeWidth);

而绘制时每个点的坐标的偏移量this.pathOffset始终等于

javascript 复制代码
{
    x: calcDim.left + width / 2,
    y: calcDim.top + height / 2
}

因此,最终后者的坐标整体会比前者往x、y正方向偏移0.5 * strokeWidth。

而由于_setPositionDimensions只在canvas.add(object)时才调用,因此,在后续缩放整个画布的过程中,this.left、this.top的值始终是定值,但是strokeWidth为了维持缩放后的绝对像素宽度,始终在动态变化,此时,ctx的偏移量x、y在变化,而pathOffset没有变,最终相对于图片的位置还是在变化。

解决方案

为了解决这个问题,需要在子类覆写的_render方法内,写以下代码:

确保偏移量x、y计算正确。

预告

下一章简单讲讲fabric的渲染原理。

相关推荐
Csvn34 分钟前
前端性能优化实战指南
前端
Moment38 分钟前
2026 年,AI 全栈时代到了,前端简历别再只写前端技术了 🫠🫠🫠
前端·后端·面试
糯米团子7491 小时前
Web Worker
开发语言·前端·javascript
freewlt1 小时前
React Server Components 深度解析
前端·react.js·前端框架
wordbaby1 小时前
一次跨端 Loading 卡死复盘:把请求计数从 Axios 拦截器迁到 try/catch/finally
前端·axios
我命由我123451 小时前
JavaScript 开发 - 获取函数名称、获取函数参数数量、获取函数参数名称
开发语言·前端·javascript·css·html·html5·js
IT_陈寒2 小时前
JavaScript里这个隐式类型转换的坑,我终于爬出来了
前端·人工智能·后端
方呵呵3 小时前
一个 3.5k Star Vue H5 项目的二次进化:我把它重构成了 Monorepo 工程体系
前端
_风满楼3 小时前
HTTP 请求的五种传参方式
前端·javascript·后端
木斯佳3 小时前
前端八股文面经大全:字节暑期前端一面(2026-04-22)·面经深度解析
前端