熟悉label和textfield都知道有個屬性:wordWrap = true; 意思是按照文本換行榄笙,遇到空格或標點柳刮,不連續(xù)的語句才換行搭盾。
而egret的位圖字體并不支持咳秉,所以我這里稍微改了下官方源碼,有能力的自行替換:
//代碼為5.12.2分支
//////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014-present, Egret Technology.
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Egret nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY EGRET AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL EGRET AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////////////
namespace egret {
/**
* Bitmap font adopts the Bitmap+SpriteSheet mode to render text.
* @version Egret 2.4
* @platform Web,Native
* @includeExample egret/text/BitmapText.ts
* @language en_US
*/
/**
* 位圖字體采用了Bitmap+SpriteSheet的方式來渲染文字鸯隅。
* @version Egret 2.4
* @platform Web,Native
* @includeExample egret/text/BitmapText.ts
* @language zh_CN
*/
export class BitmapText extends DisplayObject {
/**
* Create an egret.BitmapText object
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 創(chuàng)建一個 egret.BitmapText 對象
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public constructor() {
super();
if (!egret.nativeRender) {
this.$renderNode = new sys.BitmapNode();
}
}
/**
* color
* @version Egret 3.0
* @platform Web
* @language en_US
*/
protected color:number = -1;
/**
* set color
* @version Egret 3.0
* @platform Web
* @language en_US
*/
public setColor(color:number){
let colorMatrix1;
if(color>=0){
this.color = color;
let colorConf = {r:(color>>16&0xff)/255.0,g:(color>>8&0xff)/255.0,b:(color&0xff)/255.0,a:1};
// console.log(colorConf);
colorMatrix1 = [
colorConf.r, 0, 0, 0, 0,
0, colorConf.g, 0, 0, 0,
0, 0, colorConf.b, 0, 0,
0, 0, 0, colorConf.a, 0
];
}else{
this.color = -1;
}
if(this.color!=-1){
let color = new egret.ColorMatrixFilter(colorMatrix1);
this.filters = [color];
}else{
this.filters = null;
}
}
/**
* get color
* @version Egret 3.0
* @platform Web
* @language en_US
*/
public getColor(){
return this.color;
}
protected createNativeDisplayObject(): void {
this.$nativeDisplayObject = new egret_native.NativeDisplayObject(egret_native.NativeObjectType.BITMAP_TEXT);
}
private $smoothing: boolean = Bitmap.defaultSmoothing;
/**
* Whether or not is smoothed when scaled.
* @default true澜建。
* @version Egret 3.0
* @platform Web
* @language en_US
*/
/**
* 控制在縮放時是否進行平滑處理。
* @default true。
* @version Egret 3.0
* @platform Web
* @language zh_CN
*/
public get smoothing(): boolean {
return this.$smoothing;
}
public set smoothing(value: boolean) {
let self = this;
if (value == self.$smoothing) {
return;
}
self.$smoothing = value;
if (!egret.nativeRender) {
let p = self.$parent;
if (p && !p.$cacheDirty) {
p.$cacheDirty = true;
p.$cacheDirtyUp();
}
let maskedObject = self.$maskedObject;
if (maskedObject && !maskedObject.$cacheDirty) {
maskedObject.$cacheDirty = true;
maskedObject.$cacheDirtyUp();
}
}
}
private $text: string = "";
/**
* A string to display in the text field.
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 要顯示的文本內容
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public get text(): string {
return this.$text;
}
public set text(value: string) {
this.$setText(value);
}
/**
* @private
*/
$setText(value: string): boolean {
if (value == null) {
value = "";
} else {
value = String(value);
}
let self = this;
if (value == self.$text)
return false;
self.$text = value;
self.$invalidateContentBounds();
return true;
}
protected $textFieldWidth: number = NaN;
/**
* @private
*/
$getWidth(): number {
let self = this;
let w = self.$textFieldWidth;
return isNaN(w) ? self.$getContentBounds().width : w;
}
/**
* @private
*/
$setWidth(value: number): boolean {
let self = this;
if (value < 0 || value == self.$textFieldWidth) {
return false;
}
self.$textFieldWidth = value;
self.$invalidateContentBounds();
return true;
}
private $textLinesChanged: boolean = false;
/**
* @private
*/
$invalidateContentBounds(): void {
this.$renderDirty = true;
this.$textLinesChanged = true;
//todo lcj
this.$updateRenderNode();
}
protected $textFieldHeight: number = NaN;
/**
* @private
*/
$getHeight(): number {
let self = this;
let h = self.$textFieldHeight;
return isNaN(h) ? self.$getContentBounds().height : h;
}
/**
* @private
*/
$setHeight(value: number): boolean {
let self = this;
if (value < 0 || value == self.$textFieldHeight) {
return false;
}
self.$textFieldHeight = value;
self.$invalidateContentBounds();
return true;
}
protected $font: BitmapFont = null;
protected $fontStringChanged: boolean = false;
/**
* The name of the font to use, or a comma-separated list of font names, the type of value must be BitmapFont.
* @default null
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 要使用的字體的名稱或用逗號分隔的字體名稱列表炕舵,類型必須是 BitmapFont何之。
* @default null
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public get font(): Object {
return this.$font;
}
public set font(value: Object) {
this.$setFont(value);
}
$setFont(value: any): boolean {
let self = this;
if (self.$font == value) {
return false;
}
self.$font = value;
self.$fontStringChanged = true;
this.$invalidateContentBounds();
return true;
}
private $lineSpacing: number = 0;
/**
/**
* An integer representing the amount of vertical space between lines.
* @default 0
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 一個整數,表示行與行之間的垂直間距量
* @default 0
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public get lineSpacing(): number {
return this.$lineSpacing;
}
public set lineSpacing(value: number) {
this.$setLineSpacing(value);
}
$setLineSpacing(value: number): boolean {
let self = this;
if (self.$lineSpacing == value)
return false;
self.$lineSpacing = value;
self.$invalidateContentBounds();
return true;
}
private $letterSpacing: number = 0;
/**
* An integer representing the amount of distance between characters.
* @default 0
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 一個整數咽筋,表示字符之間的距離溶推。
* @default 0
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public get letterSpacing(): number {
return this.$letterSpacing;
}
public set letterSpacing(value: number) {
this.$setLetterSpacing(value);
}
$setLetterSpacing(value: number): boolean {
let self = this;
if (self.$letterSpacing == value) {
return false;
}
self.$letterSpacing = value;
self.$invalidateContentBounds();
return true;
}
private $textAlign: string = egret.HorizontalAlign.LEFT;
/**
* Horizontal alignment of text.
* @default:egret.HorizontalAlign.LEFT
* @version Egret 2.5.6
* @platform Web,Native
* @language en_US
*/
/**
* 文本的水平對齊方式。
* @default:egret.HorizontalAlign.LEFT
* @version Egret 2.5.6
* @platform Web,Native
* @language zh_CN
*/
public get textAlign(): string {
return this.$textAlign;
}
public set textAlign(value: string) {
this.$setTextAlign(value);
}
$setTextAlign(value: string): boolean {
let self = this;
if (self.$textAlign == value) {
return false;
}
self.$textAlign = value;
self.$invalidateContentBounds();
return true;
}
private $verticalAlign: string = egret.VerticalAlign.TOP;
/**
* Vertical alignment of text.
* @default:egret.VerticalAlign.TOP
* @version Egret 2.5.6
* @platform Web,Native
* @language en_US
*/
/**
* 文字的垂直對齊方式晤硕。
* @default:egret.VerticalAlign.TOP
* @version Egret 2.5.6
* @platform Web,Native
* @language zh_CN
*/
public get verticalAlign(): string {
return this.$verticalAlign;
}
public set verticalAlign(value: string) {
this.$setVerticalAlign(value);
}
$setVerticalAlign(value: string): boolean {
let self = this;
if (self.$verticalAlign == value) {
return false;
}
self.$verticalAlign = value;
self.$invalidateContentBounds();
return true;
}
/**
* A ratio of the width of the space character. This value is multiplied by the height of the first character is the space character width.
* @default 0.33
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 一個空格字符的寬度比例悼潭。這個數值乘以第一個字符的高度即為空格字符的寬庇忌。
* @default 0.33
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public static EMPTY_FACTOR: number = 0.33;
/**
* @private
*/
$updateRenderNode(): void {
let self = this;
let textLines: string[] = this.$getTextLines();
let length: number = textLines.length;
if (length == 0) {
if (egret.nativeRender && self.$font) {
self.$nativeDisplayObject.setDataToBitmapNode(self.$nativeDisplayObject.id, self.$font.$texture, []);
self.$nativeDisplayObject.setWidth(0);
self.$nativeDisplayObject.setHeight(0);
}
return;
}
let drawArr = [];
let textLinesWidth: number[] = this.$textLinesWidth;
let bitmapFont: BitmapFont = self.$font;
let node
if (!egret.nativeRender) {
node = <sys.BitmapNode>this.$renderNode;
if (bitmapFont.$texture) {
node.image = bitmapFont.$texture.$bitmapData;
}
node.smoothing = self.$smoothing;
}
let emptyHeight: number = bitmapFont._getFirstCharHeight();
let emptyWidth: number = Math.ceil(emptyHeight * BitmapText.EMPTY_FACTOR);
let hasSetHeight: boolean = !isNaN(self.$textFieldHeight);
let textWidth: number = self.$textWidth;
let textFieldWidth: number = self.$textFieldWidth;
let textFieldHeight: number = self.$textFieldHeight;
let align: string = self.$textAlign;
let yPos: number = this.$textOffsetY + this.$textStartY;
let lineHeights: number[] = this.$lineHeights;
for (let i: number = 0; i < length; i++) {
let lineHeight: number = lineHeights[i];
if (hasSetHeight && i > 0 && yPos + lineHeight > textFieldHeight) {
break;
}
let line = textLines[i];
let len = line.length;
let xPos = this.$textOffsetX;
if (align != egret.HorizontalAlign.LEFT) {
let countWidth: number = textFieldWidth > textWidth ? textFieldWidth : textWidth;
if (align == egret.HorizontalAlign.RIGHT) {
xPos += countWidth - textLinesWidth[i];
} else if (align == egret.HorizontalAlign.CENTER) {
xPos += Math.floor((countWidth - textLinesWidth[i]) / 2);
}
}
for (let j: number = 0; j < len; j++) {
let character = line.charAt(j);
let texture = bitmapFont.getTexture(character);
if (!texture) {
if (character == " ") {
xPos += emptyWidth;
}
else {
egret.$warn(1046, character);
}
continue;
}
let bitmapWidth = texture.$bitmapWidth;
let bitmapHeight = texture.$bitmapHeight;
if (egret.nativeRender) {
drawArr.push(texture.$bitmapX, texture.$bitmapY,
bitmapWidth, bitmapHeight, xPos + texture.$offsetX, yPos + texture.$offsetY,
texture.$getScaleBitmapWidth(), texture.$getScaleBitmapHeight(),
texture.$sourceWidth, texture.$sourceHeight);
}
else {
node.imageWidth = texture.$sourceWidth;
node.imageHeight = texture.$sourceHeight;
node.drawImage(texture.$bitmapX, texture.$bitmapY,
bitmapWidth, bitmapHeight, xPos + texture.$offsetX, yPos + texture.$offsetY,
texture.$getScaleBitmapWidth(), texture.$getScaleBitmapHeight());
}
xPos += (bitmapFont.getConfig(character, "xadvance") || texture.$getTextureWidth()) + self.$letterSpacing;
}
yPos += lineHeight + self.$lineSpacing;
}
if (egret.nativeRender) {
self.$nativeDisplayObject.setDataToBitmapNode(self.$nativeDisplayObject.id, bitmapFont.$texture, drawArr);
let bounds = self.$getContentBounds();
self.$nativeDisplayObject.setWidth(bounds.width);
self.$nativeDisplayObject.setHeight(bounds.height);
}
}
/**
* @private
*/
$measureContentBounds(bounds: Rectangle): void {
let lines: string[] = this.$getTextLines();
if (lines.length == 0) {
bounds.setEmpty();
}
else {
bounds.setTo(this.$textOffsetX + this.$textStartX, this.$textOffsetY + this.$textStartY, this.$textWidth - this.$textOffsetX,
this.$textHeight - this.$textOffsetY);
}
}
private $textWidth: number = NaN;
/**
* Get the BitmapText measured width
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 獲取位圖文本測量寬度
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public get textWidth(): number {
this.$getTextLines();
return this.$textWidth;
}
private $textHeight: number = NaN;
/**
* Get Text BitmapText height
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 獲取位圖文本測量高度
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public get textHeight(): number {
this.$getTextLines();
return this.$textHeight;
}
/**
* @private
*/
private $textOffsetX: number = 0;
/**
* @private
*/
private $textOffsetY: number = 0;
/**
* @private
*/
private $textStartX: number = 0;
/**
* @private
*/
private $textStartY: number = 0;
/**
* @private
*/
private textLines: string[] = [];
/**
* @private 每一行文字的寬度
*/
private $textLinesWidth: number[];
/**
* @private
*/
public $lineHeights: number[] = [];
/**
* @private
*
* @returns
*/
$getTextLines(): string[] {
let self = this;
if (!self.$textLinesChanged) {
return self.textLines;
}
let textLines: string[] = [];
self.textLines = textLines;
let textLinesWidth: number[] = [];
self.$textLinesWidth = textLinesWidth;
self.$textLinesChanged = false;
let lineHeights: number[] = [];
self.$lineHeights = lineHeights;
if (!self.$text || !self.$font) {
self.$textWidth = 0;
self.$textHeight = 0;
return textLines;
}
let lineSpacing = self.$lineSpacing;
let letterSpacing = self.$letterSpacing;
let textWidth: number = 0;
let textHeight: number = 0;
let textOffsetX: number = 0;
let textOffsetY: number = 0;
let hasWidthSet: boolean = !isNaN(self.$textFieldWidth);
let textFieldWidth: number = self.$textFieldWidth;
let textFieldHeight: number = self.$textFieldHeight;
let bitmapFont: BitmapFont = self.$font;
let emptyHeight: number = bitmapFont._getFirstCharHeight();
let emptyWidth: number = Math.ceil(emptyHeight * BitmapText.EMPTY_FACTOR);
let text: string = self.$text;
let textArr: string[] = text.split(/(?:\r\n|\r|\n)/);
let length: number = textArr.length;
let isFirstLine: boolean = true;
let isFirstChar: boolean;
let isLastChar: boolean;
let lineHeight: number;
let xPos: number;
var autoWrapChar = " .,\"'";
for (let i = 0; i < length; i++) {
let line: string = textArr[i];
// console.log(line);
let len = line.length;
lineHeight = 0;
xPos = 0;
isFirstChar = true;
isLastChar = false;
for (let j = 0; j < len; j++) {
if (!isFirstChar) {
xPos += letterSpacing;
}
let character = line.charAt(j);
let texureWidth: number;
let textureHeight: number;
let offsetX: number = 0;
let offsetY: number = 0;
let texture = bitmapFont.getTexture(character);
if (!texture) {
if (character == " ") {
texureWidth = emptyWidth;
textureHeight = emptyHeight;
}
else {
egret.$warn(1046, character);
if (isFirstChar) {
isFirstChar = false;
}
continue;
}
}
else {
texureWidth = texture.$getTextureWidth();
textureHeight = texture.$getTextureHeight();
offsetX = texture.$offsetX;
offsetY = texture.$offsetY;
}
if (isFirstChar) {
isFirstChar = false;
textOffsetX = Math.min(offsetX, textOffsetX);
}
if (isFirstLine) {
isFirstLine = false;
textOffsetY = Math.min(offsetY, textOffsetY);
}
if (hasWidthSet && j > 0 && xPos + texureWidth > textFieldWidth) {
if(autoWrapChar.indexOf(line[j])==-1){
let breakPos = 0;
let subStr = line.substring(0,j);
for(let k=0;k<autoWrapChar.length;k++){
let breakChar = autoWrapChar[k];
breakPos = subStr.lastIndexOf(breakChar);
if(breakPos>0){
breakPos++;
break;
}
}
if(breakPos>0){
// console.log([j,breakPos,j-breakPos]);
j-=(j-breakPos);
if(!setLineData(line.substring(0, breakPos)))
break;
}else{
if (!setLineData(line.substring(0, j)))
break;
}
}else{
if (!setLineData(line.substring(0, j)))
break;
}
// if (!setLineData(line.substring(0, j)))
// break;
line = line.substring(j);
len = line.length;
j = 0;
//最后一個字符要計算紋理寬度舞箍,而不是xadvance
if (j == len - 1) {
xPos = texureWidth;
}
else {
xPos = bitmapFont.getConfig(character, "xadvance") || texureWidth;
}
lineHeight = textureHeight;
continue;
}
//最后一個字符要計算紋理寬度,而不是xadvance
if (j == len - 1) {
xPos += texureWidth;
}
else {
xPos += bitmapFont.getConfig(character, "xadvance") || texureWidth;
}
lineHeight = Math.max(textureHeight, lineHeight);
}
if (textFieldHeight && i > 0 && textHeight > textFieldHeight) {
break;
}
isLastChar = true;
if (!setLineData(line))
break;
}
function setLineData(str: string): boolean {
if (textFieldHeight && textLines.length > 0 && textHeight > textFieldHeight) {
return false;
}
textHeight += lineHeight + lineSpacing;
if (!isFirstChar && !isLastChar) {
xPos -= letterSpacing;
}
textLines.push(str);
lineHeights.push(lineHeight);
textLinesWidth.push(xPos);
textWidth = Math.max(xPos, textWidth);
return true;
}
textHeight -= lineSpacing;
self.$textWidth = textWidth;
self.$textHeight = textHeight;
this.$textOffsetX = textOffsetX;
this.$textOffsetY = textOffsetY;
this.$textStartX = 0;
this.$textStartY = 0;
let alignType;
if (textFieldWidth > textWidth) {
alignType = self.$textAlign;
if (alignType == egret.HorizontalAlign.RIGHT) {
this.$textStartX = textFieldWidth - textWidth;
} else if (alignType == egret.HorizontalAlign.CENTER) {
this.$textStartX = Math.floor((textFieldWidth - textWidth) / 2);
}
}
if (textFieldHeight > textHeight) {
alignType = self.$verticalAlign;
if (alignType == egret.VerticalAlign.BOTTOM) {
this.$textStartY = textFieldHeight - textHeight;
} else if (alignType == egret.VerticalAlign.MIDDLE) {
this.$textStartY = Math.floor((textFieldHeight - textHeight) / 2);
}
}
return textLines;
}
}
}