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”:

file

具體代碼:
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並不具備這樣的功能,所以,我們先簡單寫一個具有canvasinput框和一個按鈕頁面,來模擬我們的效果。

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

實際測試地址:點擊這裏開始測試

我們的示例效果如圖:

代碼如下:
<!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中,然後隱藏文本框,同時清空文本框。

有了這三步,我們可以很輕鬆的寫出代碼。

第一步,初始化

首先:創建canvasinputarea元素:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章