文本截断技术在Web开发中的应用

在Web开发中,有时需要确保文本能够在特定的像素宽度内显示,特别是当文本作为链接时,希望所有的链接都能在一行内显示,而不是换行。如果链接文本太长而无法适应容器的宽度,就会发生换行。为了解决这个问题,可以采用客户端或服务器端的解决方案。客户端解决方案通常使用CSS3的text-overflow属性,但遗憾的是,并非所有浏览器都完全支持这一属性。在text-overflow属性得到完全支持之前,可以使用一些JavaScript解决方案。然而,更倾向于服务器端解决方案,因为它可以节省带宽,并且可以保证在所有浏览器中都能正常工作,无论用户是否启用了JavaScript。

服务器端解决方案

服务器端解决方案的优势在于它能够节省带宽,并且能够保证在所有浏览器中都能正常工作,包括旧版本的浏览器。为了实现文本截断,可以将所需的代码封装到一个名为TextTruncator的类中。

TextTruncator类包含一个名为TruncateText的公共方法,该方法用于截断文本。以下是C#语言的实现示例:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing; namespace aspnet_TextTruncator { public static class TextTruncator { private static Dictionary _fontWidthDic; public static Dictionary FontWidthDic { get { if (_fontWidthDic == null) { _fontWidthDic = new Dictionary(); } return _fontWidthDic; } } public static string TruncateText(string text, int textMaxWidth, string fontName, int fontSizeInPixels) { return TruncateText(text, textMaxWidth, fontName, fontSizeInPixels, false); } public static string TruncateText(string text, int textMaxWidth, string fontName, int fontSizeInPixels, bool isFontBold) { if (string.IsNullOrEmpty(text)) return text; if (textMaxWidth < 1 || string.IsNullOrEmpty(fontName) || fontSizeInPixels < 1) { throw new ArgumentException(); } int[] fontWidthArray = GetFontWidthArray(fontName, fontSizeInPixels, isFontBold); int ellipsisWidth = fontWidthArray['.'] * 3; int totalCharCount = text.Length; int textWidth = 0; int charIndex = 0; for (int i = 0; i < totalCharCount; i++) { textWidth += fontWidthArray[text[i]]; if (textWidth > textMaxWidth) { return text.Substring(0, charIndex) + "..."; } else if (textWidth + ellipsisWidth <= textMaxWidth) { charIndex = i; } } return text; } private static int[] GetFontWidthArray(string fontName, int fontSizeInPixels, bool isFontBold) { string fontEntryName = fontName.ToLower() + "_" + fontSizeInPixels.ToString() + "px" + (isFontBold ? "_bold" : ""); int[] fontWidthArray; if (!FontWidthDic.TryGetValue(fontEntryName, out fontWidthArray)) { fontWidthArray = CreateFontWidthArray(new Font(fontName, fontSizeInPixels, isFontBold ? FontStyle.Bold : FontStyle.Regular, GraphicsUnit.Pixel)); FontWidthDic[fontEntryName] = fontWidthArray; } return fontWidthArray; } private static int[] CreateFontWidthArray(Font font) { int[] fontWidthArray = new int[256]; for (int i = 32; i < 256; i++) { char c = (char)i; fontWidthArray[i] = IsIllegalCharacter(c, false) ? 0 : GetCharWidth(c, font); } return fontWidthArray; } private static int GetCharWidth(char c, Font font) { return TextRenderer.MeasureText("<" + (c == '&' ? "&&" : c.ToString()) + ">", font).Width - TextRenderer.MeasureText("<>", font).Width; } private static bool ContainsIllegalCharacters(string text, bool excludeLineBreaks) { if (!string.IsNullOrEmpty(text)) { foreach (char c in text) { if (IsIllegalCharacter(c, excludeLineBreaks)) return true; } } return false; } private static bool IsIllegalCharacter(char c, bool excludeLineBreaks) { return (c < 32 && (!excludeLineBreaks || c != '\n')) || c > 255 || c == 127 || c == 129 || c == 141 || c == 143 || c == 144 || c == 157; } } }

在ASP.NET页面中使用TextTruncator类的方法如下:

<%= TextTruncator.TruncateText("Some text that will likely come from your database, an XML file, or another source", 300, "Verdana", 12) %>

为了测量文本宽度,使用了TextRenderer.MeasureText()方法,这个方法原本是为Windows Forms应用程序设计的,但也可以用于ASP.NET。为了提高性能,缓存了字母的宽度,这样就不需要再次调用TextRenderer.MeasureText()方法。由于选择了缓存字母宽度,将字符集限制为ISO-8859-1(适用于基于拉丁语的语言),这对来说已经足够了。如果需要这段代码支持Unicode,需要移除字母宽度缓存机制,并在每次想要测量文本宽度时调用TextRenderer.MeasureText()方法(这会稍微减慢速度,但除非计划在流量非常高的网站和不够快的机器上使用它,否则应该不会有明显的影响;需要自己进行测试以确保)。也可以将字母宽度缓存机制改为使用字典而不是数组,并在实际使用字母时才将它们添加到字典中。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485