Fabric.js自定义控件图标放大后点击区域未同步扩大问题
解决Fabric.js自定义控件可点击区域不随图标放大的问题
问题根源在于Fabric.js(尤其是v4及更早版本)的默认hitTest方法,会使用**目标对象自身的cornerSize**来计算点击区域,而非你给自定义Control设置的cornerSize。哪怕你调大了Control的尺寸参数,点击判定还是沿用对象的默认小尺寸。
解决方法很简单:给自定义Control重写hitTest方法,让它基于Control自身的cornerSize来计算点击范围。
修改后的完整JS代码:
const canvas = new fabric.Canvas('canvas', { backgroundColor: "orange" }) const textInstance = new fabric.IText('Write', { fontSize: 20, fill: "white" }); canvas.centerObject(textInstance); canvas.add(textInstance); canvas.setActiveObject(textInstance); const deleteIcon = "https://cdn-icons-png.flaticon.com/512/3687/3687412.png"; const deleteImg = document.createElement('img'); deleteImg.src = deleteIcon; fabric.Object.prototype.controls.deleteControl = new fabric.Control({ x: 0.5, y: -0.5, offsetX: 30, offsetY: -30, cursorStyle: 'pointer', mouseUpHandler: deleteObject, render: renderIcon(deleteImg), cornerSize: 50, // 重写hitTest,使用Control自身的cornerSize计算点击区域 hitTest: function(pointer, fabricObject) { const actionPosition = this.getActionPosition(fabricObject); return fabric.util.distanceFromPoint(actionPosition, pointer) <= this.cornerSize / 2; } }) function renderIcon(icon) { return function renderIcon(ctx, left, top, styleOverride, fabricObject) { const size = this.cornerSize; ctx.save(); ctx.translate(left, top); ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle)); ctx.drawImage(icon, -size/2, -size/2, size, size); ctx.restore(); } } function deleteObject(e, transform){ console.log('delete object'); }
说明:
- 重写的
hitTest方法会先获取控件的实际位置actionPosition,然后计算鼠标指针到该位置的距离,只要距离小于等于cornerSize/2(即控件的半径范围),就判定为点击命中。 - 如果你使用的是Fabric.js v5及以上版本,默认
hitTest已经改用Control自身的cornerSize,但重写该方法依然能确保点击区域和图标尺寸完全匹配。
内容的提问来源于stack exchange,提问作者ttoomas
相关产品推荐
相关产品推荐

