Отключить кэширование объекта
По умолчанию Fabric «кэширует» каждую фигуру в офф‑скрин канвасе для ускорения перерисовок. При анимации «динамических» свойств (как strokeDashOffset) кэш не всегда сбрасывается, поэтому ты не видишь промежуточных кадров. Решение — при создании линии сразу выключить objectCaching:
function createLine(coords: [number, number, number, number]) {
return new fabric.Line(coords, {
stroke: '#000',
strokeWidth: 2,
originX: 'center',
originY: 'center',
// вот эта опция:
objectCaching: false,
});
}
Использовать requestRenderAll вместо renderAll
Метод canvas.requestRenderAll() умнее: он при вызове внутри анимации сам батчит несколько обновлений в один кадр и гарантирует, что всё расчётное состояние Fabric будет учтено. А canvas.renderAll() может «проскочить» и отрисовать не все изменения.
export function animateLineDraw(
canvas: Canvas,
line: Line,
duration: number = 1000
) {
const lineLength = Math.hypot(line.x2! - line.x1!, line.y2! - line.y1!);
line.set({
strokeDashArray: [lineLength, lineLength],
strokeDashOffset: lineLength,
});
line.animate(
{ strokeDashOffset: 0 },
{
duration,
easing: util.ease.easeInOutQuad,
onChange: () => {
console.log('onchange, strokeDashOffset:', line.strokeDashOffset);
canvas.requestRenderAll();
},
onComplete: () => {
console.log('oncomplete');
line.set({
strokeDashArray: undefined,
strokeDashOffset: 0,
});
canvas.requestRenderAll();
},
}
);
}
И убери вызов canvas.renderAll() сразу после animateLineDraw(...) — он не нужен, потому что первый кадр будет отрисован внутри onChange.