前言
開發 H5 遇到過幾次豎排文字的需求,把實現思路梳理一下。
關於豎排文字的一些需求
- 輸入框樣式需做成豎排樣式;
- 使用 Canvas 生成圖片供使用者儲存,圖片中的文字方向為豎排;
- 非漢字需與漢字垂直。
專案地址
- 專案連結:go.163.com/web/2019020…
- 或者掃碼瀏覽:
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()
計算字元寬度,使中英文字間距更和諧