天天看點

JavaScript 之 canvas(四)-- 繪制文字

本文原文位址: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”:

JavaScript 之 canvas(四)-- 繪制文字
具體代碼:
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

框和一個按鈕頁面,來模拟我們的效果。

其實,從這裡就可以看出繪制文字的思路,這和我們平時的截圖功能大緻一樣。

實際測試位址:點選這裡開始測試

我們的示例效果如圖:
JavaScript 之 canvas(四)-- 繪制文字
代碼如下:
<!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';
           

這樣,文本框就可以随滑鼠點選的位置而展示。

JavaScript 之 canvas(四)-- 繪制文字

完整的代碼如下:

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(三)-- 使用滑鼠實時繪制圖形

繼續閱讀