标题:自定义边界框跟随旋转,但在 Fabric.js 中取消选择和重新选择后不跟随旋转
描述: 各位开发者大家好,
我正在使用 Fabric.js 开发一个项目,并且我面临着在对象周围创建自定义边界框(标尺)的问题。具体如下:
其他详细信息:
export class CustomFabricCanvas extends fabric.Canvas {
constructor(element, options) {
super(element, options);
this.rulerLine = null;
this.on("selection:created", this.onSelectionCreated.bind(this));
this.on("selection:cleared", this.onSelectionCleared.bind(this));
this.on("object:scaling", this.onObjectScaling.bind(this));
this.on("object:moving", this.onObjectMoving.bind(this));
this.on("object:rotating", this.onObjectRotating.bind(this));
}
onSelectionCreated(event) {
const activeObject = event.selected;
if (activeObject?.length > 0) {
activeObject.forEach((obj) => {
this.showRuler({ ...obj });
});
}
}
onSelectionCleared() {
this.hideRuler();
}
showRuler(options) {
if (!this.rulerLine) {
this.rulerLine = new fabric.Rect({
left: options.left + 50, //
top: options.top + 50, // +
height: options.height + 10,
width: options.width + 10,
stroke: "black",
strokeWidth: 1,
fill: "transparent",
selectable: false,
originX: "center",
originY: "center",
angle: options.angle,
});
this.add(this.rulerLine);
this.renderAll();
}
}
hideRuler() {
if (this.rulerLine) {
this.remove(this.rulerLine);
this.rulerLine = null;
this.renderAll();
}
}
onObjectRotating(e) {
const target = e.target;
console.log(e.target);
this.rulerLine.set({
angle: target.angle,
});
this.renderAll();
}
}
请求帮助: 我需要帮助实施一个解决方案,以确保标尺即使在取消选择和重新选择后仍与对象的位置成比例。如何使基于矩形的标尺正确保留?
图片参考:
我尝试在 Fabric.js 中的对象周围创建自定义边界框(标尺)。最初,我使用线条作为标尺,但它们在旋转过程中与对象不同步。现在,我已改用围绕对象的矩形,这在旋转过程中效果很好。
但是,取消选择该项目然后重新选择它后(特别是当它已经旋转时),标尺尺寸不准确。标尺没有正确跟随矩形的位置。
我希望标尺能够根据对象的位置进行一致调整,即使在取消选择和重新选择之后也是如此。
在您使用的代码中:
left: options.left + 50
当您旋转左侧位置发生变化的矩形时,
如果您取消选择并重新选择,是的,您的“边界框”矩形将绘制在不同的位置...
请参阅下面的示例代码(主要是您的代码),我更改了
onObjectRotating
也设置了左侧和顶部,这样我们不仅可以在选择时看到旋转事件时您在做什么。
class CustomFabricCanvas extends fabric.Canvas {
constructor(element, options) {
super(element, options);
this.rulerLine = null;
this.on("selection:created", this.onSelectionCreated.bind(this));
this.on("selection:cleared", this.onSelectionCleared.bind(this));
// this.on("object:scaling", this.onObjectScaling.bind(this));
// this.on("object:moving", this.onObjectMoving.bind(this));
this.on("object:rotating", this.onObjectRotating.bind(this));
}
onSelectionCreated(event) {
const activeObject = event.selected;
if (activeObject?.length > 0) {
activeObject.forEach((obj) => {
this.showRuler({ ...obj });
});
}
}
onSelectionCleared() {
this.hideRuler();
}
showRuler(options) {
if (!this.rulerLine) {
this.rulerLine = new fabric.Rect({
left: options.left + 50, //
top: options.top + 50, // +
height: options.height + 10,
width: options.width + 10,
stroke: "black",
strokeWidth: 1,
fill: "transparent",
selectable: false,
originX: "center",
originY: "center",
angle: options.angle,
});
this.add(this.rulerLine);
this.renderAll();
}
}
hideRuler() {
if (this.rulerLine) {
this.remove(this.rulerLine);
this.rulerLine = null;
this.renderAll();
}
}
onObjectRotating(e) {
const target = e.target;
console.log(e.target);
this.rulerLine.set({
angle: target.angle,
left: target.left + 50, //
top: target.top + 50
});
this.renderAll();
}
}
var canvas = new CustomFabricCanvas('a');
var rect = new fabric.Rect({ left: 15, top: 50, height: 50, width: 50 })
canvas.add(rect);
canvas.renderAll();
canvas.setActiveObject(rect);
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
<canvas id="a" width="200" height="200"></canvas>