[开发者心得] 文字滚动组件。帮助你解决排行榜玩家名字过长的问题!!

[复制链接]
735 |0
大当家 发表于 2023-7-6 13:35:06 | 显示全部楼层 |阅读模式
本帖最后由 大当家 于 2023-7-6 13:35 编辑

还在为排行榜显示不全玩家名字而苦恼吗?还在为不同语言而导致文本长度过长而疯狂调大小吗?下面推出文字滚动组件,解决你的烦恼!!!
先展示一下效果吧!!!





上代码:


  • 将你的文本UI组件放置在一个canvas容器下,并将他们的大小和位置重叠在一起。 image.png
  • 导入如下代码:
    enum EScrollerStatue {
        /**停止状态 */
        Stop = 1,
        /**开始滚动 */
        Start = 2,
        /**滚动中 */
        Rolling = 3,
    }
    // 原始对象接口
    interface ITextBlock {
        set text(msg: string);
    }
    export class TextScrollerDecorator implements ITextBlock {
        /**可见长度 */
        private _maxWidth: number = 0;
        /**字体的最大长度 */
        private _textWidth: number = 150;
        private _canUpdate: boolean = false;
        /**文字开始滚动时,停留几秒 1000 = 1s */
        private _startCdTime: number = 1.8;
        /**文字滚动到结尾时,停留几秒 */
        private _endCdTime: number = 2;
        private _time: number = 0;
        private _tempPos: Type.Vector2;
        private _statue: EScrollerStatue = EScrollerStatue.Start;
        /**滚动速度 */
        private _speed: number = 100;
        constructor(private _canvas: UI.Canvas, private _textBlock: UI.TextBlock) {
            this._maxWidth = this._canvas.size.x;
            //父容器溢出隐藏
            this._canvas.clipEnable = true;
            this._textBlock.autoAdjust = false;
            //文本不裁剪
            this._textBlock.textHorizontalLayout = UI.UITextHorizontalLayout.NoClipping;
            //水平左对齐
            this._textBlock.textJustification = UI.TextJustify.Left;
            this.extendText(this._textBlock.text);
        }


        public set text(msg: string) {
            this._textBlock.text = msg;
            this.extendText(msg);
        }

        private extendText(msg: string) {
            //计算字体的最大长度
            this._textWidth = RichText.caculateStringWidth(this._textBlock.text, this._textBlock.fontSize);
            this.canUpdate = this._textWidth > this._maxWidth;
            const size = this._textBlock.size;
            size.x = this._textWidth;
            this._textBlock.size = size;
        }

        public set canUpdate(canUpdate: boolean) {
            this.reset();
            if (canUpdate) {
                TimeUtil.onEnterFrame.add(this._update, this)
            } else {
                TimeUtil.onEnterFrame.remove(this._update, this)
            }
        }

        private reset() {
            this._textBlock.position = Type.Vector2.zero;
            this._tempPos = Type.Vector2.zero;
            this._time = 0;
            this._statue = EScrollerStatue.Start;
            // console.log(this._statue)
        }

        public get canUpdate(): boolean {
            return this._canUpdate;
        }
        private _update(dt: number) {
            switch (this._statue) {
                case EScrollerStatue.Start:
                    this.startRoll(dt);
                    break;
                case EScrollerStatue.Rolling:
                    this.rolling(dt);
                    break;
                case EScrollerStatue.Stop:
                    this.endRoll(dt);
                    break;
            }
        }

        /**开始滚动 */
        private startRoll(dt: number) {
            this._time += dt;
            if (this._time < this._startCdTime) return;
            this._time = 0;
            this._statue = EScrollerStatue.Rolling;
        }

        /**滚动中 */
        private rolling(dt: number) {
            this._tempPos.x -= this._speed * dt;
            if (Math.abs(this._tempPos.x) > this._textWidth - this._maxWidth) {
                this._statue = EScrollerStatue.Stop;
            }
            this._textBlock.position = this._tempPos;
        }

        private endRoll(dt: number) {
            this._time += dt;
            if (this._time < this._endCdTime) return;
            this.reset()
        }

        /**停止滚动 */
        public stopScroller() {
            this.canUpdate = false;
        }

        /**设置滚动速度 */
        public set speed(speed: number) {
            this._speed = speed;
        }

        /**设置开始暂停的CD时间 */
        public set startCdTime(time: number) {
            this._startCdTime = time;
        }

        /**设置结束后暂停的CD时间 */
        public set endCdTime(time: number) {
            this._endCdTime = time;
        }
    }

    namespace RichText {

        /*
        * @Author: pengcheng.zhang
        * @Date: 2022-11-30 17:44:54
        * @Last Modified by: pengcheng.zhang
        * @Last Modified time: 2022-11-30 19:37:24
        */
        const FontDefinition = {
            'originSize': 24,
            "32": { 'char': '空格', 'width': 8, xoffset: 0 },
            "33": { 'char': '!', 'width': 8, xoffset: 0 },
            "34": { 'char': '"', 'width': 10.667, xoffset: 0 },
            "35": { 'char': '#', 'width': 18.667, xoffset: 0 },
            "36": { 'char': '$', 'width': 18.667, xoffset: 0 },
            "37": { 'char': '%', 'width': 24, xoffset: 0 },
            "38": { 'char': '&', 'width': 18.667, xoffset: 0 },
            "39": { 'char': '\'', 'width': 8, xoffset: 0 },
            "40": { 'char': '(', 'width': 10.667, xoffset: 0 },
            "41": { 'char': ')', 'width': 10.667, xoffset: 0 },
            "42": { 'char': '*', 'width': 13.333, xoffset: 0 },
            "43": { 'char': '+', 'width': 18.667, xoffset: 0 },
            "44": { 'char': ',', 'width': 5.333, xoffset: 0 },
            "45": { 'char': '-', 'width': 13.333, xoffset: 0 },
            "46": { 'char': '.', 'width': 8, xoffset: 0 },
            "47": { 'char': '/', 'width': 13.333, xoffset: 0 },

            "48": { 'char': '0', 'width': 18.667, xoffset: 0 },
            "49": { 'char': '1', 'width': 18.667, xoffset: 0 },
            "50": { 'char': '2', 'width': 18.667, xoffset: 0 },
            "51": { 'char': '3', 'width': 18.667, xoffset: 0 },
            "52": { 'char': '4', 'width': 18.667, xoffset: 0 },
            "53": { 'char': '5', 'width': 18.667, xoffset: 0 },
            "54": { 'char': '6', 'width': 18.667, xoffset: 0 },
            "55": { 'char': '7', 'width': 18.667, xoffset: 0 },
            "56": { 'char': '8', 'width': 18.667, xoffset: 0 },
            "57": { 'char': '9', 'width': 18.667, xoffset: 0 },

            "65": { 'char': "A", 'width': 21.333, xoffset: 0 },
            "66": { 'char': "B", 'width': 21.333, xoffset: 0 },
            "67": { 'char': "C", 'width': 21.333, xoffset: 0 },
            "68": { 'char': "D", 'width': 21.333, xoffset: 0 },
            "69": { 'char': "E", 'width': 18.667, xoffset: 0 },
            "70": { 'char': "F", 'width': 18.667, xoffset: 0 },
            "71": { 'char': "G", 'width': 21.333, xoffset: 0 },
            "72": { 'char': "H", 'width': 21.333, xoffset: 0 },
            "73": { 'char': "I", 'width': 8, xoffset: 0 },
            "74": { 'char': "J", 'width': 18.667, xoffset: 0 },
            "75": { 'char': "K", 'width': 21.333, xoffset: 0 },
            "76": { 'char': "L", 'width': 18.667, xoffset: 0 },
            "77": { 'char': "M", 'width': 26.667, xoffset: 0 },
            "78": { 'char': "N", 'width': 21.333, xoffset: 0 },
            "79": { 'char': "O", 'width': 21.333, xoffset: 0 },
            "80": { 'char': "P", 'width': 21.333, xoffset: 0 },
            "81": { 'char': "Q", 'width': 21.333, xoffset: 0 },
            "82": { 'char': "R", 'width': 21.333, xoffset: 0 },
            "83": { 'char': "S", 'width': 18.667, xoffset: 0 },
            "84": { 'char': "T", 'width': 18.667, xoffset: 0 },
            "85": { 'char': "U", 'width': 21.333, xoffset: 0 },
            "86": { 'char': "V", 'width': 21.333, xoffset: 0 },
            "87": { 'char': "W", 'width': 26.667, xoffset: 0 },
            "88": { 'char': "X", 'width': 21.333, xoffset: 0 },
            "89": { 'char': "Y", 'width': 21.333, xoffset: 0 },
            "90": { 'char': "Z", 'width': 18.667, xoffset: 0 },
            "91": { 'char': "[", 'width': 8.667, xoffset: 0 },
            "92": { 'char': "\\", 'width': 13.333, xoffset: 0 },
            "93": { 'char': "]", 'width': 8.667, xoffset: 0 },
            "94": { 'char': "^", 'width': 13.333, xoffset: 0 },
            "95": { 'char': "_", 'width': 13.333, xoffset: 0 },
            "96": { 'char': "`", 'width': 10.667, xoffset: 0 },

            "97": { 'char': 'a', 'width': 18.667, xoffset: 0 },
            "98": { 'char': 'b', 'width': 18.667, xoffset: 0 },
            "99": { 'char': 'c', 'width': 18.667, xoffset: 0 },
            "100": { 'char': 'd', 'width': 18.667, xoffset: 0 },
            "101": { 'char': 'e', 'width': 16, xoffset: 0 },
            "102": { 'char': 'f', 'width': 10.667, xoffset: 1 },
            "103": { 'char': 'g', 'width': 18.667, xoffset: 0 },
            "104": { 'char': 'h', 'width': 18.667, xoffset: 0 },
            "105": { 'char': 'i', 'width': 8, xoffset: 0 },
            "106": { 'char': 'j', 'width': 8, xoffset: 0 },
            "107": { 'char': 'k', 'width': 16, xoffset: 0 },
            "108": { 'char': 'l', 'width': 8, xoffset: 0 },
            "109": { 'char': 'm', 'width': 26.667, xoffset: 0 },
            "110": { 'char': 'n', 'width': 18.667, xoffset: 0 },
            "111": { 'char': 'o', 'width': 18.667, xoffset: 0 },
            "112": { 'char': 'p', 'width': 18.667, xoffset: 0 },
            "113": { 'char': 'q', 'width': 18.667, xoffset: 0 },
            "114": { 'char': 'r', 'width': 10.667, xoffset: 0 },
            "115": { 'char': 's', 'width': 16, xoffset: 0 },
            "116": { 'char': 't', 'width': 10.667, xoffset: 0 },
            "117": { 'char': 'u', 'width': 18.667, xoffset: 0 },
            "118": { 'char': 'v', 'width': 16, xoffset: 0 },
            "119": { 'char': 'w', 'width': 24, xoffset: 0 },
            "120": { 'char': 'x', 'width': 16, xoffset: 0 },
            "121": { 'char': 'y', 'width': 16, xoffset: 0 },
            "122": { 'char': 'z', 'width': 16, xoffset: 0 },
            "123": { 'char': '{', 'width': 10.667, xoffset: 0 },
            "124": { 'char': '|', 'width': 8, xoffset: 0 },
            "125": { 'char': '}', 'width': 10.667, xoffset: 0 },
            "126": { 'char': '~', 'width': 21.333, xoffset: 0 },
        }

        export function caculateStringWidth(str: string, fontSize: number) {
            let length = 0
            for (let i = 0; i < str.length; ++i) {
                let unicode = str.charCodeAt(i)
                if (unicode < 127) {
                    if (FontDefinition[unicode] != undefined) {
                        length += (FontDefinition[unicode].width + FontDefinition[unicode].xoffset) * fontSize / FontDefinition.originSize
                    }
                } else {
                    length += 32 * fontSize / FontDefinition.originSize
                }
            }
            return length
        }
    }
  • new TextScrollerDecorator(canvas, TextBlock)。两个参数分别为刚刚UI上的canvas和TextBlock组件。 image.png
可以不用重新赋新的文本内容哟。创建TextScrollerDecorator对象后,会自动读取文本组件的文字内容哟!!!





可运行工程文件: scrollerText.zip (53.92 KB, 下载次数: 51)

TextScrollerDecorator.ts

8.67 KB, 下载次数: 44

滚动文本装饰类

回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表