使用Cocos Creator制作PPT插图

Shawn前段时间尝试用Cocos Creator做了一个PPT,发现还挺好玩的,有很多东西值得去研究,这里给大家分享一点使用Creator制作PPT的一些思路和方法。

1. 页面切换

相信大多数人都知道,PPT是由一页页顺序组成的幻灯片所构成,在Creator中直接使用场景来充当灯片页面是最简单的方式,看下图:

使用场景做PPT页面

页面之间的衔接有两种方式,一种是使用我们之前讲在过的场景切换组件LoadScene,将组件挂载到一个节点上,点击即可切换,看下图:

LoadScene组件

这种方式就像做超链接,用起来是简单,但需要一页页地去配置。Shawn这里还尝试了一种方式,编写一个导航组件,解析所有场景文件名并做一个排序,提供向前翻页、向后翻页的接口函数,可以提供Button组件调用,看下面代码:

//Navigation.js
cc.Class({
    extends: cc.Component,
    onLoad () {
    this.pageIndex = 0;
        //获取所有场景并排序
        this._sceneArray = cc.game._sceneInfos.sort((info1, info2) => {
            let num1 = parseFloat(cc.path.basename(info1.url, '.fire').split('-')[1]);
            let num2 = parseFloat(cc.path.basename(info2.url, '.fire').split('-')[1]);
            return num1 - num2;
        });
        //设置为常驻节点
        cc.game.addPersistRootNode(this.node);
        this.node.on(cc.Node.EventType.TOUCH_END, () => {
            this.loadScene();
        });
    },

    //根据pageIndex变量加载场景
    loadScene() {
        let info = this._sceneArray[this.pageIndex];
        if (info) {
            cc.director._loadSceneByUuid(info.uuid);
        }
    },

    //修改pageIndex
    next() {
        this.pageIndex++;
        this.loadScene();
    },

    //修改pageIndex
    back() {
        this.pageIndex--;
        this.loadScene();
    },
});

将上面这个组件挂载到首场景的一个节点上,在内部放入两个按钮,一个调用组件的next方法,一个调用back方法,看下图:

Navigation组件.jpg

有了这个导航组件,只需要注意场景命名就行了,场景中的内容尽量使用Widget组件做好相对布局与自适应。

2. 内容逐一显示

在PPT中加入一些互动操作,比如点击屏幕时让文字或内容逐一显示,比如像下面演示一样:
点击逐一显示.gif

这个操作实现的方法有很多,我在这里写了一个组件脚本,将要控制的节点收集起来,在组件start运行时将节点全部隐藏。

收集要控制的节点.png

老方法使用Button去调用ActiveNode.setActive函数:
使用Button调用组件方法.png

利用这个组件不管是显示图片和文字都可以,现在来看它还有些缺点,如果我们有几十个节点需要逐一显示,要拖动几十次,很是麻烦,如何解决这个问题,大家可以想一下。

在这个组件上还可以做一些扩展,一种是点击显示,一种是由时间间隔显示,可以让我们这个PPT的表现更丰富一点。

3. 点击切换图片

点击图片,切换下一张,可以使用之前讲过的SpriteIndex搞定,不过这里为了让组件少一点,使用起来简单一些,我是从cc.Sprite上继承的,看下代码:

let SpriteEx = cc.Class({
    extends: cc.Sprite,

    properties: {
        spriteFrames: [cc.SpriteFrame],

        _index: 0,
        index: {
            type: cc.Integer,
            range: [0, 100],
            set(value) {
                this._index = value % this.spriteFrames.length;
                this.spriteFrame = this.spriteFrames[this._index];
            },
            get() {
                return this._index;
            }
        }
    },

    next() {
        this.index++;
    },

});

//屏蔽一些cc.Sprite不需要的属性
cc.Class.Attr.setClassAttr(SpriteEx, 'spriteFrame', 'visible', false);
cc.Class.Attr.setClassAttr(SpriteEx, '_atlas', 'visible', false);
//条件显示cc.Sprite上的一些属性
cc.Class.Attr.setClassAttr(SpriteEx, 'fillType', 'visible', function() {
    return this._type === cc.Sprite.Type.FILLED;
});

cc.Class.Attr.setClassAttr(SpriteEx, 'fillCenter', 'visible', function() {
    return this._type === cc.Sprite.Type.FILLED;
});
cc.Class.Attr.setClassAttr(SpriteEx, 'fillStart', 'visible', function() {
    return this._type === cc.Sprite.Type.FILLED;
});
cc.Class.Attr.setClassAttr(SpriteEx, 'fillEnd', 'visible', function() {
    return this._type === cc.Sprite.Type.FILLED;
});
cc.Class.Attr.setClassAttr(SpriteEx, 'fillRange', 'visible', function() {
    return this._type === cc.Sprite.Type.FILLED;
});

cc.Class.Attr.setClassAttr(SpriteEx, 'srcBlendFactor', 'visible', function() {
    return this._type === cc.Sprite.Type.FILLED;
});
cc.Class.Attr.setClassAttr(SpriteEx, 'dstBlendFactor', 'visible', function() {
    return this._type === cc.Sprite.Type.FILLED;
});

module.exports = SpriteEx;

上面代码有点多,主要是继承cc.Sprite后会有一大堆属性会显示到属性面板上,会对组件的使用者产生不好的体验,使用可以cc.Class.Attr.setClassAttr来控制组件属性的显示。

SpriteEx.png

最后修改日期:2018年12月15日

作者