Fabric.js中如何获取图形实际坐标而非bounding rectangle?
解决Fabric.js 5获取图形顶点坐标并添加中点标签的问题
核心思路
Fabric.js中不同类型图形的顶点获取方式不同,需区分内置基础形状(如Triangle)和自定义Path形状(如平行四边形):
- 内置形状:利用其固定的局部顶点位置,结合
getAbsoluteTransformMatrix()获取包含父级Group变换的矩阵,将局部坐标转换为画布全局坐标。 - 自定义Path:从
path属性提取原始路径点,同样应用绝对变换矩阵得到实际坐标。
获取顶点后,计算相邻顶点的中点,再在中点位置创建带文本的矩形标签。
完整实现代码
HTML部分
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.js"></script> <canvas id="c" width="400" height="300"></canvas>
JavaScript部分
const fc = new fabric.Canvas("c"); // 获取图形的实际顶点(画布全局坐标) function getShapeVertices(shape) { const matrix = shape.getAbsoluteTransformMatrix(); let vertices = []; if (shape.type === 'triangle') { // Triangle的局部顶点(相对于自身origin) const localPoints = [ { x: shape.width / 2, y: 0 }, { x: shape.width, y: shape.height }, { x: 0, y: shape.height } ]; vertices = localPoints.map(point => fabric.util.transformPoint(point, matrix)); } else if (shape.type === 'path') { // 提取Path中的直线坐标点 shape.path.forEach(segment => { if (segment[0] === 'M' || segment[0] === 'L') { const localPoint = { x: segment[1], y: segment[2] }; vertices.push(fabric.util.transformPoint(localPoint, matrix)); } }); // 移除闭合路径的重复终点 if (vertices.length > 0 && shape.path.at(-1)[0] === 'z') { vertices.pop(); } } return vertices; } // 在顶点中点创建带文本的矩形标签 function addMidpointLabels(vertices, canvas) { vertices.forEach((point, index) => { const nextIndex = (index + 1) % vertices.length; const nextPoint = vertices[nextIndex]; // 计算中点坐标 const midX = (point.x + nextPoint.x) / 2; const midY = (point.y + nextPoint.y) / 2; // 创建标签矩形 const label = new fabric.Textbox(`${index+1}-${nextIndex+1}`, { left: midX - 20, top: midY - 15, width: 40, height: 30, fill: 'white', stroke: 'black', strokeWidth: 1, textAlign: 'center', fontSize: 12, backgroundColor: '#333', selectable: false }); canvas.add(label); }); } // 选中图形时获取顶点并添加中点标签 fc.on('selection:created', event => { const selectedGroup = event.target; const shape = selectedGroup.item(0); const vertices = getShapeVertices(shape); console.log("实际顶点坐标: ", vertices); addMidpointLabels(vertices, fc); }); // 创建三角形 const triangle1Options = { stroke: 'black', strokeWidth: 2, fill: 'red', left: 10, top: 10, width: 100, height: 100, } let triangle1 = new fabric.Triangle(triangle1Options); const group1 = new fabric.Group([triangle1], { selectable: true, lockScalingFlip: true, lockUniScaling: true, subTargetCheck: true, lockScalingX: false, lockScalingY: false, objectCaching: false, noScaleCache: true }); fc.add(group1); // 创建平行四边形 var parallelogram1 = new fabric.Path('M 0 0 L 100 0 L 150 50 L 50 50 z', { left: 150, top: 50, stroke: 'black', strokeWidth: 2, fill: 'red', }); const group2 = new fabric.Group([parallelogram1], { selectable: true, lockScalingFlip: true, lockUniScaling: true, subTargetCheck: true, lockScalingX: false, lockScalingY: false, objectCaching: false, noScaleCache: true }); fc.add(group2);
关键说明
- 绝对变换矩阵:
getAbsoluteTransformMatrix()会自动包含父级Group的缩放、旋转、平移变换,确保转换后的坐标是画布全局坐标。 - 形状适配:代码中针对Triangle和Path做了适配,如需支持其他内置形状(如Rect、Polygon),可扩展
getShapeVertices函数,添加对应形状的局部顶点逻辑。 - 中点计算:通过取相邻顶点坐标的平均值得到中点,再将标签矩形定位到中点位置(做了偏移确保文本居中)。
内容的提问来源于stack exchange,提问作者Dinesh Rawat
相关产品推荐
相关产品推荐

