碰到一個問題,就是在頁面展示的時候,很多情況下需要對顯示的文字做折行處理,例如文字超過TD的寬度,或者DIV的寬度等等。
在IE下有word-break等等,但是在FF下,卻是行不通,所以研究了一下,寫了一個JS指令碼,原理是這樣的:
1. 首先,我們在頁面上找一個span元素,用它來裝載字元,然後通過它的寬度,來得到字元的顯示寬度
2. 然後,我們在顯示一個字串的時候,就可以利用前面得到的字元寬度,計算出每個字串的寬度
3. 在此基礎上,計算出字串應該折行的位置,插入<br/>進行折行就不是什麼問題了。
條件所限,blog不能上傳附件,我在這裡解釋一下代碼。
代碼有2部分,一個是“textWidth.js”,他完成絕大部分的工作;另外一個是測試頁面。
1. textWidth.js
原始碼 |
說明 |
var TextWidth = new function() { var widthLib = new Hash(); var textSpan; var self = this; |
內部成員變數 widthLib是一個儲存某個字型、字型大小的所有字元的寬度的hash表; |
self.getWidth = function(string, fontName, fontSize) { var lib = getSizeLib(fontName, fontSize); var totalWidth = 0; for(var i =0; i < string.length; i++) { var c = string.charCodeAt(i); if (c > 255) { totalWidth += lib[256]; }else{ totalWidth += lib[c]; } } return totalWidth; } |
計算字串的長度。演算法簡單,就是把每個字元的寬度都加到一起就好了。 關鍵是getSizeLib(fontName, fontSize);這個函數,如果Hash表裡沒有這個字型字型大小的寬度資料,它會主動初始化相應的寬度資料 |
self.wrapText = function(string, fontName, fontSize, maxWidth) { if (!string) { return " "; } var origText = string.strip(); var lib = getSizeLib(fontName, fontSize); var resultText = ""; var deltaW; var totalW = 0; for(var i =0; i < string.length; i++) { var c = string.charCodeAt(i); if (c > 255) { deltaW = lib[256]; }else{ deltaW = lib[c]; } if ((totalW + deltaW) > maxWidth) { resultText += ""; totalW = deltaW; }else{ totalW += deltaW; } resultText += string.charAt(i); } return resultText; } |
計算折行。這個也簡單,先從Hash表裡拿到寬度資料,然後逐個計算,寬度超了,就加個<br>進去 |
self.setSpan = function(obj) { textSpan = obj; textSpan.hide(); } |
儲存用於寬度計算的span元素 |
function getSizeLib(fontName, fontSize) { if (!widthLib.get(getKey(fontName, fontSize))) { initwidthLib(fontName, fontSize); } return widthLib.get(getKey(fontName, fontSize)); } |
取得指定字型字型大小的寬度資料。沒有的話,就初始化一份 |
function initwidthLib(fontName, fontSize) { var key = getKey(fontName, fontSize); var sizeLib = new Array(257); textSpan.show(); textSpan.style.fontFamily = fontName; textSpan.style.fontSize = fontSize+"px"; textSpan.update("中中中中中中中中中中"); sizeLib[256] = textSpan.offsetWidth/10; for(var i = 0; i<256; i++) { textSpan.update("中" + String.fromCharCode(i)+"中"); sizeLib[i] = textSpan.offsetWidth-2*sizeLib[256]; } textSpan.hide(); widthLib.set(key, sizeLib); } |
初始化 |
function getKey(fontName, fontSize) { return fontName+"@"+fontSize+"px"; } } |
|
|
|
下面是測試頁面的代碼
複製代碼 代碼如下:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<script language="javascript" src="prototype.js"></script>
<script language="javascript" src="textWidth.js"></script>
<title>無標題文檔</title>
<style type="text/css">
* {
font-size: 14px;
font-family: Geneva,Arial,Helvetica,sans-serif;
}
</style>
</head>
<body>
<textarea id="in" type="text"></textarea><input type="button" value="test" onclick="runTest()"/><p/>
<textarea id="resultSpan" style="width: 900px;font-size: 14px; font-family: Geneva">
</textarea>
<div id="resultDisplay" style="font-size: 14px; font-family: Geneva;background-color:#e242E6; width:80px"></div>
<span id="textSpan" style="display:none"></span>
</body>
<script type="text/javascript">
TextWidth.setSpan($('textSpan'));
function runTest() {
$('resultSpan').innerHTML = $("in").value;
var theWidth = TextWidth.getWidth($('resultSpan').innerHTML, "Geneva", 14);
$("resultDisplay").innerHTML = TextWidth.wrapText($('resultSpan').innerHTML, "Geneva", 14, 80);
}
</script>
</html>
prototype.js請自行下載驗證