phaserjs / phaser-ce

Phaser CE is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
http://phaser.io
MIT License
1.35k stars 491 forks source link

The wordWrap didn't support Chinese and I write a simple modification #337

Closed JanusSpark closed 4 years ago

JanusSpark commented 7 years ago

My English isn't good. If you can't understand this. I'm so sorry about that; You can find the the notes with modification with ctrl+f and find 'Chinese'

when I create Phaser.Text like this with Chinese

var text = ‘’参与《啦啦啦啦》小游戏免费领福利啦!Have a good time'; var desc = new Phaser.Text(game, 0, 0, text, {font: 'normal 32px', fill: '#425572', wordWrap: true, wordWrapWidth: 488});

You need to know there is no space during Chinese words so the wordWrap didn't work at all; So I have to fixed the advancedWrap function like this

`Phaser.Text.prototype.advancedWordWrap = function (text) {

var context = this.context;
var wordWrapWidth = this.style.wordWrapWidth;

var output = '';

// (1) condense whitespace
// (2) split Chinese(easy to do this I add a space to every Chinese words)
// (3) split into lines
var lines = text
    .replace(/ +/gi, ' ')
    .replace(/([^\x00-\xff])/gi, '$1 ')
    .split(/\r?\n/gi);

var linesCount = lines.length;

for (var i = 0; i < linesCount; i++)
{
    var line = lines[i];
    var out = '';

    // trim whitespace
    line = line.replace(/^ *|\s*$/gi, '');

    // if entire line is less than wordWrapWidth
    // append the entire line and exit early
    var lineWidth = context.measureText(line).width;

    if (lineWidth < wordWrapWidth)
    {
        //delete the space I had add to It
        line = line.replace(/([^\x00-\xff])[\s]*/gi, '$1')
        output += line + '\n';
        continue;
    }

    // otherwise, calculate new lines
    var currentLineWidth = wordWrapWidth;

    // split into words
    var words = line.split(' ');

    for (var j = 0; j < words.length; j++)
    {
        var word = words[j];
        //Chinese don't need space But else need
        if(/([^\x00-\xff])/gi.test(word)){
            var wordWithSpace = word;
        }else{
            var wordWithSpace = word + ' ';
        }
        var wordWidth = context.measureText(wordWithSpace).width;

        if (wordWidth > currentLineWidth)
        {
            // break word
            if (j === 0)
            {
                // shave off letters from word until it's small enough
                var newWord = wordWithSpace;

                while (newWord.length)
                {
                    newWord = newWord.slice(0, -1);
                    wordWidth = context.measureText(newWord).width;

                    if (wordWidth <= currentLineWidth)
                    {
                        break;
                    }
                }

                // if wordWrapWidth is too small for even a single
                // letter, shame user failure with a fatal error
                if (!newWord.length)
                {
                    throw new Error('This text\'s wordWrapWidth setting is less than a single character!');
                }

                // replace current word in array with remainder
                var secondPart = word.substr(newWord.length);

                words[j] = secondPart;

                // append first piece to output
                out += newWord;
            }

            // if existing word length is 0, don't include it
            var offset = (words[j].length) ? j : j + 1;

            // collapse rest of sentence
            var remainder = words.slice(offset).join(' ')
            // remove any trailing white space
            .replace(/[ \n]*$/gi, '');

            // prepend remainder to next line
            lines[i + 1] = remainder + ' ' + (lines[i + 1] || '');
            linesCount = lines.length;

            break; // processing on this line

            // append word with space to output
        }
        else
        {
            out += wordWithSpace;
            currentLineWidth -= wordWidth;
        }
    }

    // append processed line to output
    output += out.replace(/[ \n]*$/gi, '') + '\n';
}

// trim the end of the string
output = output.replace(/[\s|\n]*$/gi, '');

return output;

};`

And then I can use the wordWrap In Chinese with these code desc.useAdvancedWrap = true; desc.updateText();

samme commented 7 years ago

I can add a new callback, e.g.,

var text = this.advancedWordWrapCallback(text);

But for more complex needs maybe it's simpler to just let users overwrite the method, like you did.

samme commented 7 years ago

Or does your change keep the existing behavior too? You could make a PR then.

freeziyou commented 6 years ago

This is my solution, just add space by sprite width and fontsize .

// add space ecah n characters
function chunk(str, n) {
    var result = [];
    for(i = 0; i < str.length; i += n) {
        result.push(str.substr(i, n))
    }
    return result
};

function formatChinese(text, sprite) {
    var fontSize = text.fontSize
    var lineWidth = sprite.width
    var context = text.text
    var wrapWidth = Math.floor(lineWidth / fontSize)
    text.setText(chunk(context, wrapWidth).join(' '))
}