图片标注编辑平台搭建系列教程(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的渲染原理。

相关推荐
科技探秘人7 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人8 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR13 分钟前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香15 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q24985969318 分钟前
前端预览word、excel、ppt
前端·word·excel
小华同学ai23 分钟前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_91532 分钟前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
逐·風6 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫6 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试