当使用箭头绘制线条到FabricJS画布上时,箭头的尖端在拖动画布时会呈现奇怪的效果。一旦mouse:up
事件触发,箭头将保持与在画布上放置人工制品时保持一致。
运行下面的代码段,然后单击并拖动将绘制箭头。
const LineWithArrow = fabric.util.createClass(fabric.Line, {
type: 'line_with_arrow',
initialize(element, options) {
options || (options = {});
this.callSuper('initialize', element, options);
// Set default options
this.set({
hasBorders: false,
hasControls: false,
});
},
_render(ctx) {
this.callSuper('_render', ctx);
ctx.save();
const xDiff = this.x2 - this.x1;
const yDiff = this.y2 - this.y1;
const angle = Math.atan2(yDiff, xDiff);
ctx.translate((this.x2 - this.x1) / 2, (this.y2 - this.y1) / 2);
ctx.rotate(angle);
ctx.beginPath();
// Move 5px in front of line to start the arrow so it does not have the square line end showing in front (0,0)
ctx.moveTo(5, 0);
ctx.lineTo(-5, 5);
ctx.lineTo(-5, -5);
ctx.closePath();
ctx.fillStyle = this.stroke;
ctx.fill();
ctx.restore();
},
});
const drawLineWithArrow = (points) => (
new LineWithArrow(points, {
strokeWidth: 2,
stroke: 'black',
})
)
const selectLine = (points) => {
return drawLineWithArrow(points);
}
let line;
let isDown;
const fabricCanvas = new fabric.Canvas('canvas', {
height: 500,
width: 500,
targetFindTolerance: 15,
selection: false,
preserveObjectStacking: true,
perPixelTargetFind: true, // To prevent the line having a selectable rectangle drawn around it and instead only have it selectable on direct click
});
fabricCanvas.on('mouse:down', (options) => {
isDown = true;
const pointer = fabricCanvas.getPointer(options.e);
const points = [pointer.x, pointer.y, pointer.x, pointer.y];
line = selectLine(points);
fabricCanvas
.add(line)
.setActiveObject(line)
.renderAll();
});
fabricCanvas.on('mouse:move', (options) => {
if (!isDown) return;
const pointer = fabricCanvas.getPointer(options.e);
line.set({ x2: pointer.x, y2: pointer.y });
fabricCanvas.renderAll();
});
fabricCanvas.on('mouse:up', () => {
isDown = false;
line.setCoords();
fabricCanvas.setActiveObject(line).renderAll();
});
canvas {
border: 1px solid grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.min.js"></script>
<canvas id="canvas"></canvas>
答案 0 :(得分:3)
我认为是缓存清除的工件,因为你修改了ab对象的大小,但是Fabric不知道它。
你的箭头比线条大,但是面料却不知道它。
覆盖此功能并添加更多空间:
objectCaching: false
这只是为了解释。在您的特定情况下,您可以考虑在mousedown / mousemove上禁用objectCaching,并在mouseUp上重新启用它,或者将其禁用,将const LineWithArrow = fabric.util.createClass(fabric.Line, {
type: 'line_with_arrow',
hasBorders: false,
hasControls: false,
_getCacheCanvasDimensions() {
var dim = this.callSuper('_getCacheCanvasDimensions');
dim.width += 15; // found by trial and error
dim.height += 15; // found by trial and error
return dim;
},
_render(ctx) {
this.callSuper('_render', ctx);
ctx.save();
const xDiff = this.x2 - this.x1;
const yDiff = this.y2 - this.y1;
const angle = Math.atan2(yDiff, xDiff);
ctx.translate((this.x2 - this.x1) / 2, (this.y2 - this.y1) / 2);
ctx.rotate(angle);
ctx.beginPath();
// Move 5px in front of line to start the arrow so it does not have the square line end showing in front (0,0)
ctx.moveTo(5, 0);
ctx.lineTo(-5, 5);
ctx.lineTo(-5, -5);
ctx.closePath();
ctx.fillStyle = this.stroke;
ctx.fill();
ctx.restore();
},
});
const drawLineWithArrow = (points) => (
new LineWithArrow(points, {
strokeWidth: 2,
stroke: 'black',
})
)
const selectLine = (points) => {
return drawLineWithArrow(points);
}
let line;
let isDown;
const fabricCanvas = new fabric.Canvas('canvas', {
height: 500,
width: 500,
targetFindTolerance: 15,
selection: false,
preserveObjectStacking: true,
perPixelTargetFind: true, // To prevent the line having a selectable rectangle drawn around it and instead only have it selectable on direct click
});
fabricCanvas.on('mouse:down', (options) => {
isDown = true;
const pointer = fabricCanvas.getPointer(options.e);
const points = [pointer.x, pointer.y, pointer.x, pointer.y];
line = selectLine(points);
fabricCanvas
.add(line)
.setActiveObject(line)
.renderAll();
});
fabricCanvas.on('mouse:move', (options) => {
if (!isDown) return;
const pointer = fabricCanvas.getPointer(options.e);
line.set({ x2: pointer.x, y2: pointer.y });
fabricCanvas.renderAll();
});
fabricCanvas.on('mouse:up', () => {
isDown = false;
line.setCoords();
fabricCanvas.setActiveObject(line).renderAll();
});
添加到箭头类。
canvas {
border: 1px solid grey;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.min.js"></script>
<canvas id="canvas"></canvas>
&#13;
datetime
&#13;