使用 Fabric.js 的交互式文本字段

Posted

技术标签:

【中文标题】使用 Fabric.js 的交互式文本字段【英文标题】:Interactive text fields with Fabric.js 【发布时间】:2012-04-18 00:58:36 【问题描述】:

过去几周我一直在使用 Fabric.js,但关于文本字段,我发现只能在创建时设置文本。

是否有任何可能的方法来制作交互式文本字段,或者我是否必须找到解决方法来实现这一点? (对于交互式文本字段,我的意思是画布的一个区域,我可以点击并直接在其中写入。)

【问题讨论】:

交互式文本字段是什么意思? @TheJumpingFrog:他的意思是在画布上添加文本并稍后编辑它的内容。 正如马塞尔所说的 当答案过期时,这里的协议是什么?创建一个新问题,回答它,然后从原始问题链接到该问题?基本上接受的答案不再正确,下面的答案是寻找解决方案的人的正确答案。 @teewuane 您可以简单地对问题发表评论(就像您所做的那样)并通知作者有更新的答案。只需单击一下即可更改接受的答案:) 【参考方案1】:

假设您在脚本中同时拥有画布和上下文作为变量:

// 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);

【讨论】:

这不是我要找的。我知道如何在画布中设置文本,我要求的是一种使用fabricjs获取交互式文本字段的方法,如果可能的话:使用交互式文本字段我的意思是我可以在画布上的一个区域单击并直接写入其中。 (为了清楚起见,修改了原始问题)【参考方案2】:

我最近使用fabric.js 构建了一个思维导图工具,我遇到了同样的问题。

为了实现您所描述的(在画布中创建文本元素时和之后更改文本),我使用 jquery 来检测 keydown 事件。假设您在织物画布中选择了所需的文本元素,以下 sn-p 将更改文本。

$(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;
        
    
);

使用这种技术,我可以在织物画布中选择一个文本元素,开始输入并替换文本。您可以对其进行更改,使其在每次选择元素时都不会删除文本。

这种方法有一些妥协。例如,您不能像在常规 html 输入文本元素中一样选择文本并且没有闪烁的光标,因此“虚拟”光标始终位于文本的末尾。

如果你真的想要,你可以在文本末尾画一个闪烁的光标。

【讨论】:

非常感谢。正如我所想,似乎在 fabricjs 中没有内置的技术可以在本地执行此操作。这正是我正在考虑的解决方法。 一段很棒的代码泰森,我刚刚修复了一个小错误,当用户自己按下 shift 键时(它正在清除文本)。我只是添加了一个 else if 让它什么都不做 我无法输入特殊字符。有解决办法吗?此外,未定义函数“canvasBeforeSelectionCleared()”。 我使用此代码工作正常,但在编辑文本字段画布中没有显示光标? @Kappei【参考方案3】:

试试这个(这是来自我的应用程序):

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,
        );

【讨论】:

【参考方案4】:
    text.set( text: newText ); //Change the text
    canvas.renderAll(); //Update the canvas

这正是我想要的 :) 非常感谢!

【讨论】:

【参考方案5】:

fabric.js 的最新版本包括一个 IText 类,它结合了动态编辑和选择文本的交互。使用最新版本的 fabric.js 尝试下面的代码

canvas.add(new fabric.IText('Tap and Type',  
  fontFamily: 'arial black',
  left: 100, 
  top: 100 ,
));

【讨论】:

赞成提供更好和更新的答案。 值得注意的是,这是在 fabric.js 1.4 中引入的。我最近对所有内容进行了自定义构建,而 IText 不在该构建中,所以我收到了类似 function is undefined 的错误。我将脚本源更改为指向 cdn http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js 而不是我自己的本地副本,这解决了我的问题。我仍然不确定为什么 IText 不在自定义版本中。 谢谢。如何向 Text 或 IText 对象添加新控件?当用户单击文本字段时,我想显示颜色选择器、粗体、斜体、下划线、字体选择器等。有没有我们的插件呢? 您好,您可以通过引用创建的对象并更改其颜色属性来添加颜色选择器,请查看letztroll.com/#!/create 如果您从工具框中单击文本工具,它会创建一个文本框以及一个可以关联文本对象的引用层 你能建议如何在特定坐标开始写文本吗? @melwynpawar【参考方案6】:

我想为时已晚,但这可能对其他人有帮助。

There is a demo on fabricjs to do the exact same thing.

【讨论】:

以上是关于使用 Fabric.js 的交互式文本字段的主要内容,如果未能解决你的问题,请参考以下文章

单击另一个文本字段时禁用交互式文本字段

如何在 iOS 交互式通知中添加文本字段

在交互式网格中添加一个文本字段。甲骨文顶点

tkinter小部件界面交互式按钮

如何在 swift 中为一个文本字段禁用 DatePicker 交互(用于选择日期)“

如何在Jupyter Notebook小部件中使用FabricJS