本文原文位址:https://www.jeremyjone.com/485/, 轉載請注明,謝謝。
基本概念
在
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
為1,而z-index
的預設層級為5,這樣就可以完全隐藏掉我們的文本框,使用者在使用上不會有察覺。canvas
- 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(三)-- 使用滑鼠實時繪制圖形