Html HTML5 在画布上编辑文本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15823328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTML5 edit text on the canvas
提问by asagura
I'm trying to create something similar to http://www.listhings.comwhere you can edit the text within the canvas.
我正在尝试创建类似于http://www.listthings.com 的内容,您可以在其中编辑画布中的文本。
I've read the other post HTML5 Canvas Text Edit. But I don't want to edit the text outside of the canvas. I want to edit the text within the canvas.
我已经阅读了另一篇文章HTML5 Canvas Text Edit。但我不想编辑画布外的文本。我想编辑画布中的文本。
I'd appreciate if anyone can point me in the right direction.
Thanks
如果有人能指出我正确的方向,我将不胜感激。
谢谢
回答by markE
First, Mohsen correctly points out that when you do context.fillText you are actually "painting a picture of letters" on the canvas. It's not like a word processor!
首先,Mohsen 正确地指出,当您执行 context.fillText 时,您实际上是在画布上“绘制字母图片”。它不像文字处理器!
You can capture the key events on the window and then write the keystrokes out to your canvas.
您可以捕获窗口上的按键事件,然后将按键写入画布。
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/7tXd4/
这是代码和小提琴:http: //jsfiddle.net/m1erickson/7tXd4/
This example ONLY types lowercase a-z (no capitals, spaces, backspaces, etc)
此示例仅键入小写字母 az(无大写、空格、退格等)
You will probably want to make more enhancements like these:
您可能希望进行更多增强,例如:
- Adding more keys (A-Z, 0-9, etc).
- Respond to command keys like backspace to remove letters from the keyHistory.
- Put a cursor so users know where they are on the line as they type (hint: http://www.html5canvastutorials.com/tutorials/html5-canvas-text-metrics/)
- If you allow multi-line text, handle the [enterkey] and move to the new line.
- Etc
- 添加更多键(AZ、0-9 等)。
- 响应诸如退格键之类的命令键以从 keyHistory 中删除字母。
- 放置一个光标,以便用户在输入时知道他们在线的位置(提示:http: //www.html5canvastutorials.com/tutorials/html5-canvas-text-metrics/)
- 如果您允许多行文本,请处理 [enterkey] 并移至新行。
- 等等
Here's code just to get you started:
这里的代码只是为了让你开始:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.font="18px Arial";
var keyHistory="";
window.addEventListener("keyup", keyUpHandler, true);
function addletter(letter){
keyHistory+=letter;
ctx.clearRect(0,0,300,300);
ctx.fillText(keyHistory,20,20);
}
function keyUpHandler(event){
var letters="abcdefghijklmnopqrstuvwxyz";
var key=event.keyCode;
if(key>64 && key<91){
var letter=letters.substring(key-64,key-65);
addletter(letter);
}
}
}); // end $(function(){});
</script>
</head>
<body>
<p>First click in the red canvas below</p><br/>
<p>Then type any lowercase letters from a-z</p><br/>
<canvas id="canvas" width=300 height=100></canvas>
</body>
</html>
回答by Mohsen
fillText()
do not create an object or text node that you can edit afterwards. It will filltext on canvas, that means it will leave pixels on canvas.
fillText()
不要创建以后可以编辑的对象或文本节点。它将在画布上填充文本,这意味着它将在画布上留下像素。
You can use Canvas libraries like http://kineticjs.com/to have a single layer for that text so you can erase the layer and retype the text in. Kinect allows you to bind values to layers so you can save the text you have in the layer in a value binded to the layer.
您可以使用像http://kineticjs.com/这样的 Canvas 库为该文本创建一个图层,以便您可以擦除该图层并重新输入文本。 Kinect 允许您将值绑定到图层,以便您可以保存您拥有的文本在图层中的一个值绑定到图层。
回答by Toan
Try this solution https://jsfiddle.net/tabvn/zjyoexf1/
试试这个解决方案https://jsfiddle.net/tabvn/zjyoexf1/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Canvas Input Element</title>
</head>
<body>
<canvas id="draw" width="500" height="500"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("draw");
var ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.beginPath();
function Input(text = "", options = {}){
this.text = text;
this.options = Object.assign({width: 250, height: 40, font: "17px Arial", borderWidth: 1, borderColor: "#ccc", padding: 5}, options);
this.position = {x: 10, y: 10};
this.isFocus = false;
this.focusIndex = text.length;
this.isCommandKey = false;
this.selected = false;
this.render = function(){
ctx.clearRect(this.position.x, this.position.y, this.options.width, this.options.height);
ctx.font = this.options.font;
ctx.lineWidth = this.options.borderWidth;
ctx.strokeStyle = this.options.borderColor;
if(this.isFocus){
ctx.strokeStyle = "#000";
}
ctx.rect(this.position.x, this.position.y, this.options.width, this.options.height);
ctx.stroke();
// write text
var str = "";
for(var i = 0; i < this.text.length; i++){
if(!this.selected && this.isFocus && this.focusIndex === i){
str += "|";
}
str += this.text[i];
}
if(!this.selected && this.isFocus && this.focusIndex === this.text.length){
str += "|";
}
if(this.selected){
var _width = ctx.measureText(this.text).width;
ctx.fillStyle = 'rgba(0,0,0,0.5)';
ctx.fillRect(this.position.x + this.options.padding, this.position.y + this.options.padding, _width, parseInt(this.options.font, 17));
}
ctx.fillStyle = "#000";
ctx.fillText(str, this.position.x + this.options.padding, this.position.y + (this.options.height / 2) + this.options.padding);
}
this.handleOnClick = function(e){
let clientX = e.clientX;
let clientY = e.clientY;
if(clientX <= this.position.x + this.options.width && clientX >= this.position.x && clientY <= this.position.y + this.options.height && clientY >= this.position.y){
if(!this.isFocus){
this.isFocus = true;
this.focusIndex = this.text.length;
this.render();
}
}else{
if(this.isFocus){
this.selected = false;
this.isFocus = false;
this.render();
}
}
}
this.handleOnKeyUp = function(e){
this.isCommandKey = false;
this.render();
}
this.handleOnKeyDown = function(e){
if(e.key === "Meta" || e.key === "Control"){
this.isCommandKey = true;
}
if(this.isFocus){
e.preventDefault();
}
if(this.isCommandKey && e.key === "a"){
this.selected = true;
this.render();
return
}
if(this.isFocus && e.key === "Backspace"){
if(this.selected){
this.focusIndex = 0;
this.text = "";
this.selected = false;
this.render();
}
var str = "";
for(var i =0; i < this.text.length; i++){
if(i !== this.focusIndex - 1){
str += this.text[i];
}
}
this.text = str;
this.focusIndex --;
if(this.focusIndex <0){
this.focusIndex = 0;
}
this.render();
}
if(this.isFocus && e.key === "ArrowLeft"){
this.focusIndex --;
if(this.focusIndex < 0){
this.focusIndex = 0;
}
this.render();
}
if(this.isFocus && e.key === "ArrowRight"){
this.focusIndex ++;
if(this.focusIndex > this.text.length){
this.focusIndex = this.text.length;
}
this.render();
}
if(!this.isCommandKey && this.isFocus && (e.keyCode == 32 || (e.keyCode >= 65))){
this.text += e.key;
this.focusIndex = this.text.length;
this.render();
}
}
}
var input = new Input("I 'm an input");
input.render();
window.addEventListener("click", function(event){
input.handleOnClick(event);
});
window.addEventListener("keydown", function(event){
input.handleOnKeyDown(event);
});
window.addEventListener("keyup", function(event){
input.handleOnKeyUp(event);
});
</script>
</body>
</html>