英文:
Fabric.js IText interaction issue, moving but not editing
问题
尝试将可编辑、可调整大小、可旋转等的IText组件添加到画布中。添加后可以移动,但无论如何都无法与之交互。
fabric版本 - 5.3.0
vue.js + TS + Vite
这是我的useCanvas组合:
import { fabric } from 'fabric';
import { ref, Ref } from 'vue';
import { useElementSize } from '@vueuse/core';
const MIN_CANVAS_HEIGHT = 500;
export function useCanvas(
canvasRef: Ref<HTMLCanvasElement | null>,
canvasContainerRef: Ref<HTMLElement | null>,
minHeight = MIN_CANVAS_HEIGHT,
) {
const canvas = ref<fabric.Canvas | null>(null);
const { width: containerWidth, height: containerHeight } =
useElementSize(canvasContainerRef);
const init = () => {
canvas.value = new fabric.Canvas(canvasRef.value, {
width: containerWidth.value,
height: minHeight,
});
};
const addText = (value: string, isEditable = true) => {
if (!canvas.value) return;
const text = new fabric.IText(value, {
left: 50,
top: 50,
fill: '#000000',
fontFamily: 'Arial',
fontSize: 24,
fontWeight: 'normal',
editable: isEditable,
centeredRotation: true,
padding: 10,
});
// 移除缩放时不保持宽高比的能力
text.setControlsVisibility({
mt: false,
mb: false,
ml: false,
mr: false,
});
canvas.value.add(text);
};
return {
canvas,
init,
addText,
};
}
这是使用它的Vue组件:
<template>
<div ref="editorContainerRef" class="image-editor">
<canvas ref="editorCanvasRef" class="image-editor__canvas" />
<button class="button" type="button" @click="handleTextAdd">
<span>添加文本</span>
</button>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useCanvas } from './composables';
const DEFAULT_TEXT = 'Your unique signature';
const editorContainerRef = ref<HTMLElement | null>(null);
const editorCanvasRef = ref<HTMLCanvasElement | null>(null);
const canvasInstance = useCanvas(editorCanvasRef, editorContainerRef);
const { init, addText } = canvasInstance;
const handleTextAdd = () => {
addText(DEFAULT_TEXT);
};
onMounted(() => {
if (!editorCanvasRef.value) return;
init();
});
</script>
正如你所见,我已经尝试设置可能影响缩放、旋转和编辑能力的每个属性,但它不起作用。但如果我在画布上添加多个文本,然后选择它们,每个文本都开始按预期工作。所以我发现文本在选择为一组之前是不可交互的,我不知道是什么导致了这种行为。
英文:
Trying to add IText component to the canvas that will be editable, resizable, rotatable etc.
It can be moved after adding, but cant be interacted in other way no matter what i do
fabric version - 5.3.0
vue.js + TS + Vite
here is my useCanvas composable
import { fabric } from 'fabric'
import { ref, Ref } from 'vue'
import { useElementSize } from '@vueuse/core'
const MIN_CANVAS_HEIGHT = 500
export function useCanvas(
canvasRef: Ref<HTMLCanvasElement | null>,
canvasContainerRef: Ref<HTMLElement | null>,
minHeight = MIN_CANVAS_HEIGHT,
) {
const canvas = ref<fabric.Canvas | null>(null)
const { width: containerWidth, height: containerHeight } =
useElementSize(canvasContainerRef)
const init = () => {
canvas.value = new fabric.Canvas(canvasRef.value, {
width: containerWidth.value,
height: minHeight,
})
}
const addText = (value: string, isEditable = true) => {
if (!canvas.value) return
const text = new fabric.IText(value, {
left: 50,
top: 50,
fill: '#000000',
fontFamily: 'Arial',
fontSize: 24,
fontWeight: 'normal',
editable: isEditable,
centeredRotation: true,
padding: 10,
})
// removing ability to scale without maintaining aspect ratio
text.setControlsVisibility({
mt: false,
mb: false,
ml: false,
mr: false,
})
canvas.value.add(text)
}
}
return {
canvas,
init,
addText,
}
and here is vue component where it is being used
template
<template>
<div ref="editorContainerRef" class="image-editor">
<canvas ref="editorCanvasRef" class="image-editor__canvas" />
<button class="button" type="button" @click="handleTextAdd">
<span>{{ 'add text' }}</span>
</button>
</div>
</template>
script
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useCanvas } from './composables'
const DEFAULT_TEXT = 'Your unique signature'
const editorContainerRef = ref<HTMLElement | null>(null)
const editorCanvasRef = ref<HTMLCanvasElement | null>(null)
const canvasInstance = useCanvas(editorCanvasRef, editorContainerRef)
const { init, addText } = canvasInstance
const handleTextAdd = () => {
addText(DEFAULT_TEXT)
}
onMounted(() => {
if (!editorCanvasRef.value) return
init()
})
</script>
As you can see i've already tried to set every property that could possibly affect scaling, rotating and editing ability but it doesn't work
But if i add more than one text to canvas and then select both, each of them begins to work as expected
So what i found is that text isn't interactable until you select it in group and i have no idea what causes that behavior
答案1
得分: 0
以下是您要翻译的内容:
For those who will face the same problem in the future:
The problem arises from Vue reactivity, which uses a lot of proxies under the hood. In this particular case, there are some conflicts with the fabric.js library, causing unexpected behavior.
So the solution is to remove any reactivity from fabric.Canvas and any fabric.Object you are trying to interact with.
Many hours of research have led to this small change.
Doesn't work:
const canvas = ref<fabric.Canvas | null>(null)
canvas.value = new fabric.Canvas(canvasRef.value, {
width: containerWidth.value,
height: minHeight,
})
Works as expected:
let canvas = null as fabric.Canvas | null
canvas = new fabric.Canvas(canvasRef.value, {
width: containerWidth.value,
height: minHeight,
})
英文:
For those who will face same problem in the future:
The problems goes from Vue reactivity that uses a lot of proxy under the hood, that in that particular case have some conflicts with fabric.js library and causes unexpected behavior
So solution is: remove any reactivity from fabric.Canvas and any fabric.Object you are trying to interact with.
Many hours of research leads to this small change
doesn't work:
const canvas = ref<fabric.Canvas | null>(null)
canvas.value = new fabric.Canvas(canvasRef.value, {
width: containerWidth.value,
height: minHeight,
})
works as expected:
let canvas = null as fabric.Canvas | null
canvas = new fabric.Canvas(canvasRef.value, {
width: containerWidth.value,
height: minHeight,
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论