1. 程式人生 > 其它 >前端開發系列028-基礎篇之Canvas繪圖(文字)

前端開發系列028-基礎篇之Canvas繪圖(文字)

title: '前端開發系列028-基礎篇之Canvas繪圖(文字)'
tags:
  - javaScript系列
categories: []
date: 2017-07-26 08:20:13
本文將介紹Canvas畫布繪製文字相關的技術細節。

一、Canvas畫布繪製文字

核心API

繪製文字(描邊)

語法 ctx.strokeText( text , x , y , [ maxWidth ]);

作用 用於在畫布上繪製文字(描邊·沒有填色)。

說明 文字的顏色為黑色,可以通過strokeStyle屬性來設定顏色或漸變。

引數

text                      繪製的文字資訊
x                         文字的X軸座標
y                         文字的Y軸座標
maxWidth                  允許的最大文字寬度,單位為畫素

示例

    var canvas = document.getElementById("canvas");
    var ctx    = canvas.getContext("2d");
    
    //設定文字的字號大小和字型樣式
    ctx.font="20px Impact";
    ctx.strokeText("Nice to meet you!",10,50);

    //建立漸變
    var gradient = ctx.createLinearGradient(200,0,300,0);
    gradient.addColorStop("0","black");
    gradient.addColorStop("0.5","blue");
    gradient.addColorStop("1.0","red");

    //設定文字的字號大小和字型樣式
    ctx.font="25px KaiTi";
    ctx.strokeStyle = gradient;
    ctx.strokeText("wendingding.com",200,50);

繪製文字(填充)

語法 ctx.fillText( text , x , y , [ maxWidth ]);

作用 用於在畫布上繪製填色的文字。

說明 文字的顏色為黑色,可以通過fillStyle屬性來設定顏色或漸變。

引數

text              繪製的文字資訊
x                 文字的X軸座標
y                 文字的Y軸座標
maxWidth          允許的最大文字寬度,單位為畫素

示例

    var canvas = document.getElementById("canvas");
    var ctx    = canvas.getContext("2d");
    
    //設定文字的字號大小和字型樣式
    ctx.font="20px Georgia";
    ctx.fillText("Nice to meet you!",10,50);

    //建立漸變
    var gradient = ctx.createLinearGradient(200,0,300,0);
    gradient.addColorStop("0","black");
    gradient.addColorStop("0.5","blue");
    gradient.addColorStop("1.0","red");

    // 用漸變填色
    ctx.fillStyle = gradient;
    //設定文字的字號大小和字型樣式
    ctx.font="25px KaiTi";
    ctx.fillText("wendingding.com",200,50);

計算文字資訊的寬度

語法 ctx.measureText( text ).width;

作用 用於計算和返回指定文字的寬度,單位以畫素計。

說明 measureText方法返回的本身是一個物件,我們需要用過width來獲取寬度值。

引數 text表示要測量的文字。

文字繪製相關屬性介紹

font 設定文字的字號和字型等資訊。

textAlign 設定水平對齊方式,可選值有start(預設) | end | left | right | center

textBaseline 設定垂直對齊方式,可選值有alphabetic(預設) | top | middle | bottom | hanging | ideographic。其中hanging表示文字基線是懸掛基線,ideographic表示文字基線是表意基線。

    var canvas = document.getElementById("canvas");
    var ctx    = canvas.getContext("2d");

    var str = "How are you?";
    ctx.font = "30px Times New Roman";

    ctx.strokeText(str,50,50);
    ctx.fillText(str,50,100);
    ctx.fillText(str,50,150,120);   //約束最大寬度
    console.log(ctx.measureText(str).width);
    
    ctx.moveTo(100,0);
    ctx.lineTo(100,ctx.canvas.height);
    ctx.stroke();
    ctx.beginPath();

    var textAlignArr = ["start","end","left","right","center"];
    for(var i = 0;i<textAlignArr.length;i++)
    {
        ctx.textAlign = textAlignArr[i];
        ctx.fillText(str,100,200 + (50 *(i + 1)));
    }

    ctx.moveTo(0,200);
    ctx.lineTo(ctx.canvas.width,200);
    ctx.stroke();
    ctx.beginPath();

    str = "正";
    var textBaselineArr = ["alphabetic","top","hanging","middle","ideographic","bottom"];
    for(var i = 0;i<textBaselineArr.length;i++)
    {
        ctx.textBaseline = textBaselineArr[i];
        ctx.fillText(str,100  + (80 *(i + 1)),200);
    }

二、Canvas實現文字豎排案例

<!DOCTYPE html>
<html lang="en">
<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>Document</title>
</head>
<body>
<canvas width="1000px" height="700px" id="canvas"></canvas>

<script type="text/template" id="templateText">
#北冥有魚, 其名為鯤, 鯤之大, 不知其幾千里也。 化而為鳥, 其名為鵬, 鵬之背, 不知其幾千里也。 怒而飛, 其翼若垂天之雲。 是鳥也, 海運則將徙於南冥, 南冥者, 天池也。 
#齊諧者, 志怪者也。 諧之言曰: 鵬之徙於南冥也, 水擊三千里, 摶扶搖而上者九萬裡。 去以六月息者也, 野馬也, 塵埃也, 生物之以息相吹也。 天之蒼蒼, 其正色邪? 其遠而無所至極邪? 其視下也, 亦若是則已矣。 
#且夫水之積也不厚, 則其負大舟也無力。 覆杯水於坳堂之上, 則芥為之舟, 置杯焉則膠, 水淺而舟大也。 風之積也不厚, 則其負大翼也無力。 故九萬裡, 則風斯在下矣, 而後乃今培風。 揹負青天而莫之夭厄者, 而後乃今將圖南。 
#蜩與學鳩笑之曰: “ 我決起而飛, 槍榆枋, 時則不至, 而控於地而已矣。 奚以之九萬裡而南為? ” 適莽蒼者, 三飧而反, 腹猶果然。 適百里者, 宿舂糧。 適千里者, 三月聚糧。 之二蟲, 又何知? 
#小知不及大知, 小年不及大年。 奚以知其然也? 朝菌不知晦朔, 惠蛄不知春秋, 此小年也。 楚之南有冥靈者, 以五百歲為春, 五百歲為秋; 上古有大椿者, 以八千歲為春, 八千歲為秋; 而彭祖乃今以久特聞, 眾人匹之, 不亦悲乎? 
#湯之問棘也是已: 窮發之北有冥海者, 天池也。 有魚焉, 其廣數千里, 未有知其修者, 其名為鯤。 有鳥焉, 其名為鵬, 背若泰山, 翼若垂天之雲, 摶扶搖羊角而上者九萬裡, 絕雲氣, 負青天, 然後圖南, 且適南冥也。 
#斥鵪笑之曰: “ 彼且奚適也? 我騰躍而上, 不過數仞而下, 翱翔蓬蒿之間, 恥亦飛之至也。 而彼且奚適也? ” 此小大之辨也。 
#故夫知效一官, 行比一鄉, 德合一君, 而徵一國者, 其自視也, 亦若此矣。 而宋榮子猶然笑之。 且舉世譽之而不加勸, 舉世非之而不加沮。 定乎內外之分, 辨乎榮辱之境, 斯已矣。 彼其於世, 未數數焉也。 雖然, 猶有未樹也。
#夫列子禦風而行, 泠然善也, 旬有五日而後反。 彼於致福, 未數數然也。 此雖免乎行, 猶有所待者也。 
#若夫乘天地之正, 而禦六氣之辯, 以遊無窮者, 彼且惡乎待哉! 故曰: 至人無己, 神人無功, 聖人無名。 
</script>

<script>
    var canvas = document.getElementById("canvas");
    var ctx    = canvas.getContext("2d");
    var m      = 30;
    var h      = ctx.canvas.height;
    var w      = ctx.canvas.width;
    var count  = Math.floor(w / m);

    for (var i = 0; i <= count; i++) {
        ctx.beginPath();
        ctx.moveTo(i*m - 0.5 ,0);
        ctx.lineTo(i*m - 0.5 ,h);
        ctx.strokeStyle = "#1D244F";
        ctx.stroke();
    }

    CanvasRenderingContext2D.prototype.fillTextVertical = function (text, x, y) {
        var self = this;
        self.textAlign = 'center';
        self.textBaseline = 'middle';

        var arrText = text.split('');
        var arrWidth = arrText.map(function (letter) {
            return self.measureText(letter).width;
        });

        arrText.forEach(function (letter, index) {

            if(letter == "#")
            {
                y = 12 + 50;
                x = x - 30;
                return;
            }

            var letterWidth = arrWidth[index];
            var code = letter.charCodeAt(0);
            if (code <= 256) {
                self.translate(x, y);
                self.rotate(90 * Math.PI / 180);
                self.translate(-x, -y);
            } else if (index > 0 && text.charCodeAt(index - 1) < 256) {
                y = y + arrWidth[index - 1] / 2;
            }
            self.fillText(letter, x, y);
            self.setTransform(1, 0, 0, 1, 0, 0);
            var letterWidth = arrWidth[index];
            y = y + letterWidth;

            if(y >= (self.canvas.height - 12))
            {
                y = 12;
                x = x - 30;
            }
        });
    };

    var templateText = document.getElementById("templateText").innerText;
    ctx.font = '20px STKaiti, sans-serif';
    ctx.fillStyle = "#1D244F";
    ctx.fillTextVertical("逍遙遊( 上)  · 莊子", canvas.width - 25,  0);
    ctx.fillTextVertical(templateText, canvas.width - 25, 12);

</script>
</body>
</html>