J'ai beaucoup joué avec Fabric.js ces dernières semaines, mais en ce qui concerne les champs de texte, je n'ai trouvé que la possibilité de définir le texte à la création.
Est-il possible de créer un champ de texte interactif ou dois-je trouver une solution de contournement pour y parvenir? (Par champ de texte interactif, je veux dire une zone de la toile sur laquelle je peux cliquer et écrire directement.)
La dernière version de fabric.js comprend une classe IText qui intègre l’interaction pour l’édition et la sélection dynamique de texte. essayez le code ci-dessous avec la dernière version de fabric.js
canvas.add(new fabric.IText('Tap and Type', {
fontFamily: 'arial black',
left: 100,
top: 100 ,
}));
J'ai récemment construit un outil de cartographie conceptuelle à l'aide de fabric.js et j'ai rencontré le même problème.
Pour réaliser ce que vous avez décrit (modification du texte sur et après la création d'éléments textuels dans le canevas), j'ai utilisé jquery pour détecter l'événement de raccourci. En supposant que vous ayez sélectionné l'élément textuel souhaité dans le canevas du tissu, l'extrait suivant modifiera le texte.
$(document).keydown(function(e){
var keyPressed = String.fromCharCode(e.which);
var text = canvas.getActiveObject();
if (text)
{
var newText = '';
var stillTyping = true;
if (e.which == 27) //esc
{
if (!text.originalText) return; //if there is no original text, there is nothing to undo
newText = text.originalText;
stillTyping = false;
}
//if the user wants to make a correction
else
{
//Store the original text before beginning to type
if (!text.originalText)
{
text.originalText = text.text;
}
//if the user wants to remove all text, or the element entirely
if (e.which == 46) //delete
{
activeObject.element.remove(true);
return;
}
else if (e.which == 16) { //shift
newText = text.text;
}
else if (e.which == 8) //backspace
{
e.preventDefault();
newText = text.text.substr(0, text.text.length - 1);
}
else if (e.which == 13) //enter
{
//canvas clear selection
canvas.discardActiveObject();
canvas.renderAll();
canvasBeforeSelectionCleared({ memo: { target: text} });
newText = text.text;
stillTyping = false;
}
//if the user is typing alphanumeric characters
else if (
(e.which > 64 && e.which < 91) || //A-Z
(e.which > 47 && e.which < 58) || //0-9
(e.which == 32) || //Space
(keyPressed.match(/[!&()"'?-]/)) //Accepted special characters
)
{
if (text.text == text.originalText) text.text = '';
if (keyPressed.match(/[A-Z]/) && !e.shiftKey)
keyPressed = keyPressed.toLowerCase();
newText = text.text + keyPressed;
}
}
text.set({ text: newText }); //Change the text
canvas.renderAll(); //Update the canvas
if (!stillTyping)
{
this.text.originalText = null;
}
}
});
En utilisant cette technique, je peux sélectionner un élément de texte dans le canevas, commencer à taper et le texte est remplacé. Vous pouvez le changer pour ne pas effacer le texte chaque fois que vous sélectionnez l'élément.
Il y a quelques compromis avec cette méthode. Par exemple, vous ne pouvez pas sélectionner du texte comme s'il s'agissait d'un élément de saisie HTML ordinaire et si aucun curseur ne clignote, le curseur "virtuel" se trouve donc toujours à la fin du texte.
Si vous le désirez vraiment, vous pouvez dessiner un curseur clignotant à la fin du texte.
Je suppose que c'est trop tard, mais cela pourrait aider d'autres.
text.set({ text: newText }); //Change the text
canvas.renderAll(); //Update the canvas
C'était ce que je cherchais :) Merci beaucoup!
Essayez ceci (cela provient de mon application):
Text Color: <input id="text-color" type="text" value = "#FF0000" name="textColor" />
textColor.onchange = function() {
canvas.getActiveObject().setColor(this.value);
canvas.renderAll();
};
function updateControls() {
textControl.value = canvas.getActiveObject().getText();
}
canvas.on({
'object:selected': updateControls,
});
en supposant que vous avez à la fois la toile et le contexte comme variables dans votre script:
// write text
context.fillText("text1",0,0);
// refresh canvas and write new text
context.clearRect(0,0,canvas.width,canvas.height);
context.fillText("text2",0,0);