DOM 和 Canvas 如何實現文字豎向排列的效果

NingBo發表於2019-03-04

前言

開發 H5 遇到過幾次豎排文字的需求,把實現思路梳理一下。

關於豎排文字的一些需求

  1. 輸入框樣式需做成豎排樣式;
  2. 使用 Canvas 生成圖片供使用者儲存,圖片中的文字方向為豎排;
  3. 非漢字需與漢字垂直。

DOM 和 Canvas 如何實現文字豎向排列的效果

專案地址

DOM 實現文字豎排

<input> 標籤沒有豎排的屬性,最先嚐試修改 <input> 的樣式來實現效果,但是效果不理想。最後使用 HTML 的 contenteditable 屬性。

嘗試修改 input 樣式(失敗)

想通過限定 輸入框的寬度文字的大小 ,讓文字自動換行。

關鍵程式碼

input{
    width: 30px;
    height: 250px;
    font-size: 30px;
}
複製程式碼

放棄原因

  • 英文字元寬度小,會出現換行失敗的情況

使用 HTML 的 contenteditable 屬性代替 <input> (推薦)

HTML 的 contenteditable 屬性規定元素內容是否可編輯。

關鍵程式碼

<div contenteditable="true" style="writing-mode: vertical-lr; writing-mode: tb-lr; "></div>
複製程式碼
  • 使用 div 代替 input
  • 使用 contenteditable 屬性使 div 可編輯
  • 使用 CSS 的 writing-mode 屬性讓文字垂直排列

使用原因

  • 非中文自動旋轉,排版更好看(實現了需求中的第三點)

Canvas 實現文字豎排

Canvas 同樣沒有豎排文字的屬性,我通過遍歷文字的方式進行繪製。

關鍵程式碼

let name; // 文字內容
let x = 657,y=170; // 文字開始的座標
let letterSpacing = 10; // 設定字間距
for(let i = 0; i < this.name.length; i++){
    const str = this.name.slice(i,i+1).toString();
    if(str.match(/[A-Za-z0-9]/)&&(y<576)){ // 非漢字 旋轉
        ctx.save();
        ctx.translate(x,y);
        ctx.rotate(Math.PI/180*90);
        ctx.textBaseline = 'bottom';
        ctx.fillText(str,0,0);
        ctx.restore();
        y+=ctx.measureText(str).width+letterSpacing; // 計算文字寬度
    }else if(str.match(/[\u4E00-\u9FA5]/)&&(y<576)){
        ctx.save();
        ctx.textBaseline = 'top';
        ctx.fillText(str,x,y);
        ctx.restore();
        y+=ctx.measureText(str).width+letterSpacing; // 計算文字寬度
    }
}

複製程式碼

推薦原因

  • 非中文自動旋轉,排版更好看(實現了需求中的第三點)
  • 使用 measureText() 計算字元寬度,使中英文字間距更和諧

相關文章