我正在使用fillRect在画布中绘制矩形。我想添加文本,我希望它像编辑框一样可编辑。有没有办法在JavaScript中实现这一点?
我不想要fillText,因为我希望文本可以在画布上编辑。
答案 0 :(得分:1)
当然! (虽然这很棘手)
值得庆幸的是,某人已经完成并将其发布在Github存储库中:https://github.com/goldfire/CanvasInput
它位于MIT Licence之下,所以请务必遵守其条件!
答案 1 :(得分:1)
这是最基本的例子。我不建议任何人这样做,除非它是供自己使用,并且他们严格控制浏览器和浏览器版本,本地化等。由于存在更多原因,因此存在更多原因。
canvasTextBox
定义了所需的一切。它会创建HTMLInputElement
,然后收听keyup
和input
个事件。
动画循环检查状态的任何变化,并在需要时渲染文本,与所有其他DOM渲染同步。
我添加了一个基本的闪烁光标,但没有文本选择,没有插入,覆盖模式,没有书写方向(仅从左到右),没有拼写检查,没有否,没有。
我没有添加焦点检查,无法关闭它,没有鼠标交互,也没有上下文菜单。
使用此方法实现一个基本可用的公共版本需要超过1000行代码和数月的测试。即便如此,它也不会一直有效,因为在JavaScript环境中总会有一些不可知的特殊情况。
画布文字框
示例适用于Win10计算机上的Chrome测试版,可能适用于其他浏览器/操作系统,但我没有费心去检查。
var canvas = document.createElement("canvas");
canvas.width = 400;
canvas.height = 200;
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");
var w = canvas.width;
var h = canvas.height;
var cw = w / 2; // center
var ch = h / 2;
var globalTime; //
var canvasTextBox = {
x : 10,
y : 10,
h : 50,
w : 300,
ready : false,
font : "40px arial",
fontCol : "blue",
selectColour : "blue",
background : "#CCC",
border : "black 2px", // this is not a CSS style and will break if you dont have colour and width
create : function(){
var text = document.createElement("input")
text.type = "text";
text.style.position = "absolute";
var bounds = canvas.getBoundingClientRect();
text.style.top = (bounds.top + this.x + 2) + "px";
text.style.left = (bounds.left + this.y +2 )+ "px";
text.style.zIndex = -100;
document.body.appendChild(text);
this.textState.element = text;
// get some events
this.textState.events = (function(event){
this.changed = true;
this.text = this.element.value;
}).bind(this.textState);
// add a blink thing
this.textState.blink = (function(){
this.cursorOn = !this.cursorOn;
this.changed = true;
setTimeout(this.blink,this.cursorRate);
}).bind(this.textState);
// listen for changes
text.addEventListener("input",this.textState.events);
text.addEventListener("keyup",this.textState.events);
this.ready = true;
},
render : function(){
var start,end;
ctx.font = this.font;
ctx.fillStyle = "#AAA";
ctx.strokeStyle = this.border.split(" ")[0];
ctx.lineWidth = this.border.split(" ")[1].replace("px","");
ctx.fillRect(this.x,this.y,this.w,this.h);
ctx.strokeRect(this.x,this.y,this.w,this.h);
ctx.fillStyle = this.fontCol;
start = 0;
end = 0;
if(this.textState.element.selectionStart !== undefined){
start = this.textState.element.selectionStart;
}
var text = this.textState.text;
var textStart = text.substr(0,start);
var w = ctx.measureText(text).width;
var wStart = ctx.measureText(textStart).width;
var cursor = this.x + wStart;
ctx.save();
ctx.beginPath();
ctx.rect(this.x,this.y,this.w,this.h);
ctx.clip();
if(w > this.w){
cursor = this.x + this.w - w + wStart;
if(cursor < this.x){
ctx.fillText(this.textState.text,this.x+this.w-w + (this.x - cursor)+3,this.y + 40);
cursor = this.x;
}else{
ctx.fillText(this.textState.text,this.x+this.w-w,this.y + 40);
}
}else{
ctx.fillText(this.textState.text,this.x,this.y + 40);
}
if(this.textState.cursorOn){
ctx.fillStyle = "red";
ctx.fillRect(cursor,this.y,3,this.h);
}
ctx.restore();
},
textState : {
text : "",
cursor : 0,
cursorOn : false,
cursorRate : 250,
changed : true,
events : null,
element : null,
},
update : function(){
if(this.textState.changed){
this.textState.changed = false;
this.render();
}
},
focus : function(){
this.textState.element.focus();
this.textState.blink();
},
}
canvasTextBox.create();
canvasTextBox.focus();
// main update function
function update(timer){
globalTime = timer;
if(canvasTextBox.ready){
canvasTextBox.update();
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
&#13;