基本概念
在canvas
中,为我们提供了一个非常方便的添加文字的方法,直接上 w3school 的文档说明:
context.fillText(text,x,y,maxWidth);
// text: 规定在画布上输出的文本。
// x: 开始绘制文本的 x 坐标位置(相对于画布)。
// y: 开始绘制文本的 y 坐标位置(相对于画布)。
// maxWidth: 可选。允许的最大文本宽度,以像素计。
官方也给我们提供了一个简单的说明:
使用 fillText(),在画布上写文本 "Hello world!" 和 "w3school.com.cn":
具体代码:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.font="20px Georgia";
ctx.fillText("Hello World!",10,50);
ctx.font="30px Verdana";
// 创建渐变
var gradient=ctx.createLinearGradient(0,0,c.width,0);
gradient.addColorStop("0","magenta");
gradient.addColorStop("0.5","blue");
gradient.addColorStop("1.0","red");
// 用渐变填色
ctx.fillStyle=gradient;
ctx.fillText("w3school.com.cn",10,90);
根据文档说明,可以很清楚fillText()
的具体用法,那么接下来就来绘制我们自定义的文本。
绘制自定义文本
在绘制之前,我们需要清楚,网页中的文字都是由输入框来交互的,canvas
并不具备这样的功能,所以,我们先简单写一个具有canvas
、input
框和一个按钮页面,来模拟我们的效果。
其实,从这里就可以看出绘制文字的思路,这和我们平时的截图功能大致一样。
实际测试地址:点击这里开始测试
我们的示例效果如图:
代码如下:
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JS - Canvas - text</title>
</head>
<body style="background-color: #999">
<div>
<canvas id="canvas" width="800" height="200" style="background-color: #fff">抱歉,您的浏览器不支持canvas元素</canvas>
</div>
<textarea name="textBox" id="textBox" cols="30" rows="10" class="text-style" onkeyup="setText()"></textarea>
<input type="button" value="添加文字" onclick="drawing()">
</body>
<script>
window.onload = function () {
var canvas = document.getElementById("canvas");
var textBox = document.getElementById("textBox");
var textContent = "";
if (canvas.getContext) {
var context = canvas.getContext("2d"); //2d用引用括起来
}
drawing = function () {
if (!context) {
return;
} else {
// 设置画笔的颜色和大小
context.fillStyle = "red"; // 填充颜色为红色
context.strokeStyle = "blue"; // 画笔的颜色
context.lineWidth = 5; // 指定描边线的宽度
context.save();
context.beginPath();
// 写字
context.font = "28px orbitron";
context.fillText(textContent, 10, 50);
context.restore();
context.closePath();
}
// 清空内容
textContent = "";
textBox.value = "";
}
setText = function () {
textContent = textBox.value;
}
}
</script>
</html>
这是一个完整的页面内容,可以直接得到上面的动图效果。这个效果也是大部分网上其他高手的基础demo。我一开始也想着是这么使用。但是很快,我就发现了一个问题,这样做根本不足以完成在指定位置绘制文本的功能。于是我在网上搜寻答案。
在一个技术贴中,我看到一种思路,完全绘制一个会话框,连光标的闪烁状态也需要使用定时器来不停模拟。它的核心思路是,把一个文本框隐藏在canvas
之下,监听键盘事件,然后将键盘的文字输入到隐藏的文本框中,而文本框的值与一个变量直接绑定,当该变量发生变化,直接使用fillText()
填到canvas
中,虽然是一个可行方案,但我觉得太麻烦了。于是乎,我将之前的思路与这个技术贴的思路结合了一下,就有了我的具体思路:
- 在
canvas
之下创建一个文本框,当需要输入文本时,将文本框显示在canvas
之上,这时候可以直接输入文字,当完成输入时,隐藏这个文本框,并且将文字画到canvas
画布中,这样就完成了绘制文本。
在canvas之中显示文本框
可能这个隐藏、显示的,看着有点晕,我一说您肯定明白,使用z-index
,来回切换层级即可。这样省去了绘制模拟的文本框,同时输入文字时也不会出现任何错误,毕竟这是原生组件,不会有什么问题。
-
1、所以第一步,我们需要制作初始状态,一般来说,初始状态只能看到画布,我们需要隐藏文本框。 我们可以将这个文本框和
canvas
设置为绝对定位,默认文本框的z-index
为1,而canvas
的默认层级为5,这样就可以完全隐藏掉我们的文本框,用户在使用上不会有察觉。 -
2、第二步,设置
canvas
中的鼠标,当点击某个位置时,显示文本框,这时就可以输入文本。 -
3、第三步,当点击文本框以外时,相当于确认,这时需要将文本填到
canvas
中,然后隐藏文本框,同时清空文本框。
有了这三步,我们可以很轻松的写出代码。
第一步,初始化
首先:创建canvas
和inputarea
元素:
<body style="background-color: #999">
<canvas id="canvas" width="800" height="600" class="canvas-style">抱歉,您的浏览器不支持canvas元素</canvas>
<textarea name="textBox" id="textBox" cols="30" rows="10" class="text-style"></textarea>
</body>
然后:设置样式
.canvas-style {
background-color: #fff;
float: left;
position: absolute;
z-index: 5;
}
.text-style {
float: left;
position: absolute;
font: 28px orbitron;
word-break: break-all;
background-color: transparent;
resize: none;
z-index: 1;
}
这样,元素就搭建完毕,并且完成了初始化隐藏输入框的效果。
第二步,使用鼠标调出输入框
这里需要分别写出鼠标的按下(这里不牵扯 抬起 和 移动)的事件。
canvas.onmousedown = function mouseDownAction(e) {
// 鼠标按下时需要一个标志位,因为我们的逻辑是按下时分别可调出和完成文字的填写。
if (textFlag) {
// 当前为输入状态,点击canvas等于完成填写,这时需要隐藏输入栏,并且获取文本框的内容,将其绘入canvas中。
textContent = textBox.value;
textFlag = false;
textBox.style['z-index'] = 1;
textBox.value = "";
this.drawing() // 绘制文字
} else if (!textFlag) {
// 当前非绘制状态,需要将输入框调至最前,开始输入。
textFlag = true
textBox.style['z-index'] = 6;
}
};
第二步其实也很简单,找对位置即可。
第三步,将文字绘制到canvas中
上面的代码我们已经看到了this.drawing()
函数,其实就在这里绘制即可。
canvas.drawing = function (x1, y1, x2, y2, e) {
let self = this;
if (!context) {
return;
} else {
// 设置画笔的颜色和大小
context.fillStyle = "red"; // 填充颜色为红色
context.strokeStyle = "blue"; // 画笔的颜色
context.lineWidth = 5; // 指定描边线的宽度
context.save();
context.beginPath();
// 写字
context.font = "28px orbitron";
context.fillText(textContent, 10, 50); // 文字会展示在(10, 50)展示
context.restore();
context.closePath();
}
};
这样就完成了一个最基本的动态添加文字的demo,但是这个只是比之前的demo好一点点,将文本框放入了canvas
中,还不能够随鼠标的位置而移动,起始这个也简单,参照之前的绘制基本图形,很简单就可以实现。
加入鼠标的位置
鼠标的位置是这样获取的:
canvas.onmousedown = function mouseDownAction(e) {
this.X1 = e.offsetX;
this.Y1 = e.offsetY;
};
这样就有了输入框应该显示的位置,在调整z-index
的位置添加两行代码:
textBox.style.left = this.X1 + 'px';
textBox.style.top = this.Y1 + 'px';
这样,文本框就可以随鼠标点击的位置而展示。
完整的代码如下:
var canvas = document.getElementById("canvas");
var textBox = document.getElementById("textBox");
var textFlag = false;
var textContent = "";
if (canvas.getContext) {
var context = canvas.getContext("2d"); //2d用引用括起来
}
canvas.drawing = function (x1, y1, x2, y2, e) {
if (!context) {
return;
} else {
// 设置画笔的颜色和大小
context.fillStyle = "red"; // 填充颜色为红色
context.strokeStyle = "blue"; // 画笔的颜色
context.lineWidth = 5; // 指定描边线的宽度
context.save();
context.beginPath();
// 写字
context.font = "28px orbitron";
context.fillText(textContent, parseInt(textBox.style.left), parseInt(textBox.style.top));
context.restore();
context.closePath();
}
};
canvas.onmousedown = function mouseDownAction(e) {
this.X1 = e.offsetX; // 鼠标按下时保存当前位置,为起始位置
this.Y1 = e.offsetY;
if (textFlag) {
textContent = textBox.value;
textFlag = false;
textBox.style['z-index'] = 1;
textBox.value = "";
this.drawing(this.X1, this.Y1);
} else if (!textFlag) {
textFlag = true
textBox.style.left = this.X1 + 'px';
textBox.style.top = this.Y1 + 'px';
textBox.style['z-index'] = 6;
}
};
今天的文章有点长,但是这有助于理解文本的填写。只要练习一两次,还是很简单的。
结合之前的文章,我们已经可以制作一个非常简单的绘图板了,有兴趣的朋友可以 ->点击这里<- 进行测试。
前期目录:
JavaScript 之 canvas(一)-- 认识canvas
JavaScript 之 canvas(二)-- 绘制基本图形
JavaScript 之 canvas(三)-- 使用鼠标实时绘制图形
文章评论