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

相关推荐
damon08708几秒前
nodejs 实现 企业微信 自定义应用 接收消息服务器配置和实现
服务器·前端·企业微信
web守墓人几秒前
【前端】ikun-pptx编辑器前瞻问题五:pptx中的xml命名空间
xml·前端
oMcLin7 分钟前
如何在 CentOS 7 上通过配置和调优 OpenResty,提升高并发 Web 应用的 API 请求处理能力?
前端·centos·openresty
IT_陈寒8 分钟前
Java开发者必知的5个性能优化技巧,让应用速度提升300%!
前端·人工智能·后端
小二·14 分钟前
Python Web 开发进阶实战:前端现代化 —— Vue 3 + TypeScript 重构 Layui 界面,打造高性能 SPA
前端·python·typescript
cnxy18825 分钟前
Python Web开发新时代:FastAPI vs Django性能对比
前端·python·fastapi
神仙姐姐QAQ26 分钟前
vue3更改.el-dialog__header样式不生效
前端·javascript·vue.js
脾气有点小暴27 分钟前
uniapp真机调试无法连接
前端·uni-app
AI_567828 分钟前
Vue.js 深度开发指南:从数据绑定到状态管理的最佳实践
前端·javascript·vue.js