支持多条消息连续滚动的横向字幕公告组件

公告是游戏中都会用到的基本组件。网上有一些简单滚动文本的例子,但离实用还有点远。于是花了点时间写了这个横向字幕公告组件,就是逻辑有点绕,代码很少,直接贴在下面。setTimeout、.runAction 参考了编程菜鸟洋葱的《cocos creator 滚动字幕公告如何实现?》一文(https://www.jianshu.com/p/5ea37a801603)。


/****************************************************************************
Copyright © 2015-2017 Kiky Technologies Studio.
maxime@yeah.net
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

‘use strict’;

/**

  • !#en Class KKRollLable
  • !#zh 横向滚动字幕条,支持多条消息按添加顺序连续滚动,每条消息只会滚动一次。
  • 若需反复滚动同一条消息,就用定时器定时添加。
  • @class KKRollLable
  • @constructor
  • @extends cc.Component
  • 使用要点:
    1. 建一个空节点,绑定本脚本组件。
    1. 在空节点下,建立一个 Mask 节点,将 AnchorX 设置为零,宽度设置为滚动区域的宽度。
    1. 在Mask组件下,建立一个 Label 节点,将 AnchorX 设置为零,Overflow 模式为 None。
    1. 将 Mask、Label 节点添加到本组件属性上。
    1. 设置两条消息间的间隔字符串,建议8个空格。
    1. 设置滚动速度,单位为像素/秒。
    1. 调用 addText() 添加消息文本。
  • 特色:
    1. 支持多条消息文本连续滚动。
    1. 用字符串数组缓存消息,实际进入Label的消息文本较少。
  • 3. 使用简单,只要将服务器发来的公告文本,往组件里添加即可。
    
  • 缺点:
    1. 不支持彩色富文本,如果把Label替换成富文本控件似乎就可以。
    1. _rollText 函数不可重入,不要直接调用它。
    1. 在消息尾部补空格的算法效率低下,最坏的情况下,可能要设置几十次 label.string 值。
    1. 没有消息丢弃机制,如果短时间塞进去1000条消息,它也会慢慢一条一条的滚动。可在 addText
  •   中限制添加到 _strings 中的消息数量,丢弃过多的消息。
    
  • 测试:仅在 web 和 ios 环境下做过简单测试,貌似稳定,但仍可能有 Bug。

*/
var KKRollLable = cc.Class({
extends: cc.Component,

properties: {
    label: cc.Label,        // Lable 控件,需要将其 AnchorX 设置为零,Overflow 模式为 None。
    mask: cc.Mask,          // Mask 控件,需要将其 AnchorX 设置为零,将其宽度设置为滚动区域的宽度。
    space: cc.String,       // 在两条消息之间的间隔字符串,通常设置为八个空格。
    speed: 100,             // 滚动速度,既每秒钟滚动的像素个数。

    _strings: [cc.String],   

    _d1: 0,                 // 正在滚动的文本长度
    _d2: 0,                 // 已经添加的后续文本长度
},

// use this for initialization
onLoad: function () {

},

/**
 * !#en
 * !#zh 添加一条滚动消息。
 * @method addText
 * @param {cc.String} text - 消息文本。
 */
addText: function (text) {
    var prefix = "";
    var suffix = this.space;
    if (this._strings.length === 0) {
        // 没有正在滚动的文本
        this.label.node.x = this.mask.node.width;
        this.label.string = prefix + text + suffix;
        this._d1 = this.label.node.width;
        this._d2 = this.label.node.width - this._d1;
        this._strings.push(prefix + text + suffix);
        this._rollText();
    } else {
        // 有正在滚动的文本
        if (this._d2 < this.mask.node.width) {
            // 还可以添加后续文本
            while (this.label.node.x + this._d1 + this._d2 < this.mask.node.width) {
                // 补空格      
                this.label.string = this.label.string + " ";
                this._d2 = this.label.node.width - this._d1;                   
                prefix = prefix + " ";
            }
            this.label.string = this.label.string + text + suffix;
            this._d2 = this.label.node.width - this._d1;
            this._strings.push(prefix + text + suffix);
        } else {
            // 不能再添加后续文本
            this._strings.push(prefix + text + suffix);
        }
    }
},


_rollText: function(){
    //var self = this;
    if (this._strings.length > 0) {
        setTimeout(function(){
            var d = this.label.node.x + this._d1;
            var x = - this._d1;
            var t = d / this.speed;
            this.label.node.runAction(cc.sequence(
                cc.moveTo(t, cc.p(x, this.label.node.y)),
                cc.callFunc(function(){
                    this._strings.shift();
                    if (this._strings.length > 0) {
                        this.label.node.x = 0;
                        this.label.string = this._strings[0];
                        this._d1 = this.label.node.width;
                        this._d2 = this.label.node.width - this._d1;
                        for (var i = 1; i < this._strings.length; i++) {
                            if (this.label.node.x + this._d1 + this._d2 < this.mask.node.width + this._d1) {
                                this.label.string = this.label.string + this._strings[i];
                                this._d2 = this.label.node.width - this._d1;
                            } else {
                                break;
                            }
                        }
                        this._rollText();
                    }
                }.bind(this))
            ));
        }.bind(this), 0);
    }
},

// called every frame, uncomment this function to activate update callback
// update: function (dt) {

// },

});

2赞

赞 

貌似更简单的方法 有

duqugonggao:function(){

    this.GongGao.getComponent(cc.RichText).string = this.duqushuzu();
    this.GongGao.x = cc.MAN.gongwidth;
 
    this.schedule(function() {

        this.GongGao.x -= 3;
        if( this.GongGao.x <  -this.GongGao.width){
            this.GongGao.getComponent(cc.RichText).string = this.duqushuzu();
            this.GongGao.x = cc.MAN.gongwidth;
        }



    }, 0.01);

},

duqushuzu:function(){
    /*读取单条公告信息*/

    if(this.GONGLIST.length > 1000){

        this.GONGLIST = [];
    }


    for(var i=0; i < this.GONGLIST.length ;  i++){

        if(this.GONGLIST[i]){

            var tmep = this.GONGLIST[i];

            this.GONGLIST.splice(i,1);
            return tmep;
            
        }
    }

    this.GONGLIST = [];
    return "<color=green>你好</color> 欢迎光临 <color=#FFFF00>456电玩城</color>";

}
2赞