Laya 動畫系列二 Animation 和IDE的幀動畫、動效模板

一座硕、AnimationPlayerBase extends Sprite

動畫播放基類弛作,提供了基礎(chǔ)的動畫播放控制方法和幀標(biāo)簽事件相關(guān)功能』遥可以繼承此類映琳,但不要直接實(shí)例化此類,因?yàn)橛行┓椒ㄐ枰勺宇悓?shí)現(xiàn)蜘拉。

/**
 * <p>開始播放動畫萨西。play(...)方法被設(shè)計(jì)為在創(chuàng)建實(shí)例后的任何時(shí)候都可以被調(diào)用,
 * 當(dāng)相應(yīng)的資源加載完畢旭旭、調(diào)用動畫幀填充方法(set frames)或者將實(shí)例顯示在舞臺上時(shí)谎脯,
 * 會判斷是否正在播放中,如果是持寄,則進(jìn)行播放穿肄。</p>
 * <p>配合wrapMode屬性,可設(shè)置動畫播放順序類型际看。</p>
 * @param   start   (可選)指定動畫播放開始的索引(int)或幀標(biāo)簽(String)。
 * 幀標(biāo)簽可以通過addLabel(...)和removeLabel(...)進(jìn)行添加和刪除矢否。
 * @param   loop    (可選)是否循環(huán)播放仲闽。
 * @param   name    (可選)動畫名稱。
 * @param   showWarn(可選)是否動畫不存在時(shí)打印警告
 */
public function play(start:* = 0, loop:Boolean = true,
name:String = "",showWarn:Boolean=true):void {
    this._isPlaying = true;
    this.index = (start is String) ? _getFrameByLabel(start) : start;
    this.loop = loop;
    this._actionName = name;
    _isReverse = wrapMode == WRAP_REVERSE;
    if (this.interval > 0) {
        timerLoop(this.interval, this, _frameLoop, null, true, true);
    }
}

可以看到interval控制了幀率僵朗,再看看_frameLoop方法赖欣,首先判斷_isReverse和wrapMode,也就是播放模式验庙,最后執(zhí)行這一句this.index = this._index;

public function set index(value:int):void {
    _index = value;
    _displayToIndex(value);
    if (_labels && _labels[value]) {
        var tArr:Array = _labels[value];
        for (var i:int = 0, len:int = tArr.length; i < len; i++) {
            event(Event.LABEL, tArr[i]);
        }
    }
}

/**
 * @private
 * 顯示到某幀
 * @param value 幀索引
 */
protected function _displayToIndex(value:int):void {
}

處理了Event.LABEL幀事件顶吮,并且把具體如何顯示幀,留給了子類去實(shí)現(xiàn)_displayToIndex方法粪薛。至于幀事件悴了,可以看一下這個(gè)方法:

/**
 * 增加一個(gè)幀標(biāo)簽到指定索引的幀上。當(dāng)動畫播放到此索引的幀時(shí)
 * 會派發(fā)Event.LABEL事件违寿,派發(fā)事件是在完成當(dāng)前幀畫面更新之后湃交。
 * @param   label   幀標(biāo)簽名稱
 * @param   index   幀索引
 */
public function addLabel(label:String, index:int):void {
    if (!_labels) _labels = {};
    if (!_labels[index]) _labels[index] = [];
    _labels[index].push(label);
}

_labels是一個(gè)Object,它的key是一個(gè)數(shù)字藤巢,也就是幀索引(注意幀索引搞莺,是從0開始的)。它的value是一個(gè)數(shù)組掂咒,會把幀標(biāo)簽名稱都存到這個(gè)數(shù)組中才沧。從上面的set index方法中也能看到迈喉,進(jìn)入某一幀時(shí),會判斷_labels相應(yīng)的幀標(biāo)簽數(shù)組温圆,派發(fā)里面所有名稱的事件挨摸。

二、Animation extends AnimationPlayerBase

1.首先去看如何顯示幀_displayToIndex

/**@private */
override protected function _displayToIndex(value:int):void {
    if (this._frames) this.graphics = this._frames[value];
}

官方對_frames的解釋是捌木,_frames是當(dāng)前動畫的幀圖像數(shù)組油坝。本類中,每個(gè)幀圖像是一個(gè)Graphics對象刨裆,而動畫播放就是定時(shí)切換Graphics對象的過程澈圈。可以看到_displayToIndex方法確實(shí)是在切換graphics對象帆啃。

2.動畫緩存池framesMap
public static var framesMap:Object = {};
動畫模版緩存池是以一定的內(nèi)存開銷來節(jié)省CPU開銷瞬女,當(dāng)相同的動畫模版被多次使用時(shí),相比于每次都創(chuàng)建新的動畫模版努潘,使用動畫模版緩存池诽偷,只需創(chuàng)建一次,緩存之后多次復(fù)用疯坤,從而節(jié)省了動畫模版創(chuàng)建的開銷报慕。
動畫模版緩存池,以key-value鍵值對存儲压怠,key可以自定義眠冈,也可以從指定的配置文件中讀取,value為對應(yīng)的動畫模版菌瘫,是一個(gè)Graphics對象數(shù)組.使用loadImages(...)蜗顽、loadAtlas(...)、loadAnimation(...)雨让、set source方法可以創(chuàng)建動畫模版雇盖。

3.有三個(gè)類似的方法:loadImages,loadAtlas栖忠,loadAnimation,以及它們?nèi)齻€(gè)的綜合體set source

public function loadImages(urls:Array, cacheName:String = ""):Animation {
    this._url = "";
    if (!_setFramesFromCache(cacheName)) {
        this.frames = framesMap[cacheName] ? 
        framesMap[cacheName] : createFrames(urls, cacheName);
    }
    return this;
}

public function loadAtlas(url:String,
    loaded:Handler = null, cacheName:String = ""):Animation {
    this._url = "";
    var _this_:Animation = this;
    function onLoaded(loadUrl:String):void {
        if (url === loadUrl) {
            _this_.frames = framesMap[cacheName] ?
            framesMap[cacheName] : createFrames(url, cacheName);
            if (loaded) loaded.run();
        }
    }
    if (!_this_._setFramesFromCache(cacheName)) {
        if (Loader.getAtlas(url)) onLoaded(url);
        else Laya.loader.load(url, Handler.create(
        null, onLoaded, [url]), null, Loader.ATLAS);
    }
    return this;
}

public function loadAnimation(url:String,
    loaded:Handler = null, atlas:String = null):Animation {
    this._url = url;
    var _this_:Animation = this;
    if (!_actionName) _actionName = "";
    if (!_this_._setFramesFromCache("")) {
        if (!atlas || Loader.getAtlas(atlas)) {
            _loadAnimationData(url, loaded, atlas);
        } else {
            Laya.loader.load(atlas, Handler.create(this, _loadAnimationData,
            [url, loaded, atlas]), null, Loader.ATLAS)
        }
    } else {
        _this_._setFramesFromCache(_actionName, true);
        index = 0;
        if (loaded) loaded.run();
    }
    return this;
}

根據(jù)參數(shù)來看:
loadImages加載的是圖片路徑集合崔挖,比如[url1,url2,url3,...]。
loadAtlas加載的是圖集路徑庵寞,比如animation.loadAtlas("resource/ani/fighter.json");
loadAnimation加載的是由IDE創(chuàng)建的ani文件虚汛,比如ani.loadAnimation("tinyGame/coin0.ani");

這里注意_url屬性,這個(gè)屬性只有在loadAnimation這個(gè)方式時(shí)皇帮,記錄傳入的ani路徑卷哩,其它兩個(gè)方式,都是空字符串属拾。它的用處是在_setFramesFromCache方法中将谊,強(qiáng)行把傳入的name參數(shù)變成_url + "#" + name;

/**@private */
protected function _setFramesFromCache(name:String, 
    showWarn:Boolean = false):Boolean {
    if (_url) name = _url + "#" + name;
    if (name && framesMap[name]) {
        var tAniO:*;
        tAniO = framesMap[name];
        if (tAniO is Array) {
            this._frames = framesMap[name];
            this._count = _frames.length;
        } else {
            if (tAniO.nodeRoot) {
                //如果動畫數(shù)據(jù)未解析過,則先進(jìn)行解析
                framesMap[name] = _parseGraphicAnimationByData(tAniO);
                tAniO = framesMap[name];
            }
            this._frames = tAniO.frames;
            this._count = _frames.length;
            //如果讀取的是動畫配置信息冷溶,幀率按照動畫設(shè)置的幀率播放
            if (!_frameRateChanged) _interval = tAniO.interval;
            _labels = _copyLabels(tAniO.labels);
        }
        return true;
    } else {
        if (showWarn) trace("ani not found:", name);
    }
    return false;
}

也就是說,IDE創(chuàng)建的ani尊浓,會被緩存成key是"url#動畫名稱" 對應(yīng)相應(yīng)動畫名稱的動畫模板逞频。而另外兩種方式,是否緩存栋齿,以及緩存key叫什么苗胀,是可以自己控制的,對應(yīng)的參數(shù)是cacheName瓦堵。cacheName默認(rèn)為空基协,也就是不進(jìn)行緩存。如果不為空菇用,則表示使用此值做key進(jìn)行動畫模板緩存澜驮。

至于set source,算是對上面三個(gè)方法的一個(gè)整體封裝吧惋鸥,傳入?yún)?shù)如:圖集:"xx/a1.atlas"杂穷;圖片集合:"a1.png,a2.png,a3.png";LayaAir IDE動畫"xx/a1.ani"

public function set source(value:String):void {
    if (value.indexOf(".ani") > -1) loadAnimation(value);
    else if (value.indexOf(".json") > -1 ||
    value.indexOf("als") > -1 ||
    value.indexOf("atlas") > -1) loadAtlas(value);
    else loadImages(value.split(","));
}

4.createFrames
這個(gè)方法在loadImages和loadAtlas都在使用卦绣,區(qū)別就是一個(gè)傳入的是urls(圖片路徑集合)耐量,一個(gè)是url(圖集路徑)。

public static function createFrames(url:*, name:String):Array {
    var arr:Array,i:int,n:int,g:Graphics;
    if (url is String) {
        var atlas:Array = Loader.getAtlas(url);
        if (atlas && atlas.length) {
            arr = [];
            for (i = 0, n = atlas.length; i < n; i++) {
                g = new RunDriver.createGraphics();
                g.drawTexture(Loader.getRes(atlas[i]), 0, 0);
                arr.push(g);
            }
        }
    } else if (url is Array) {
        arr = [];
        for (i = 0, n = url.length; i < n; i++) {
            g = new RunDriver.createGraphics();
            g.loadImage(url[i], 0, 0);
            arr.push(g);
        }
    }
    if (name) framesMap[name] = arr;
    return arr;
}

從這里也能看出如何去創(chuàng)建一個(gè)Graphics對象滤港。注意最后一句if (name) framesMap[name] = arr;拴鸵,印證了上面所說,cacheName為空時(shí)蜗搔,不會緩存。

由于這是個(gè)靜態(tài)方法八堡,也可以在不創(chuàng)建Animation實(shí)例前樟凄,先創(chuàng)建動畫緩存,比如:

//創(chuàng)建動畫模板dizziness
Laya.Animation.createFrames(this.aniUrls("die", 4), "die");
Laya.Animation.createFrames(this.aniUrls("fire", 7), "fire");
Laya.Animation.createFrames(this.aniUrls("atk", 3), "atk");
Laya.Animation.createFrames(this.aniUrls("move", 4), "move");
        
/**
 * 創(chuàng)建一組動畫的url數(shù)組(美術(shù)資源地址數(shù)組)
 * aniName  動作的名稱兄渺,用于生成url
 * length   動畫最后一幀的索引值缝龄,
 */
private aniUrls(aniName: string, length: number): any {
    var urls: any = [];
    for (var i: number = 1; i < length; i++) {
        //動畫資源路徑要和動畫圖集打包前的資源命名對應(yīng)起來
        urls.push("imgs/role/wp116/" + aniName + i + ".png");
    }
    return urls;
}

5.clearCache
根據(jù)上面所說,IDE創(chuàng)建的ani挂谍,會以"url#aniName"作為key來緩存叔壤,清理時(shí)也要注意這一點(diǎn)。

public static function clearCache(key:String):void {
    var cache:Object = framesMap;
    var val:String;
    var key2:String = key + "#";
    for (val in cache) {
        if (val === key || val.indexOf(key2) == 0) {
            delete framesMap[val];
        }
    }
}

6.重寫的play方法

override public function play(start:* = 0,
    loop:Boolean = true, name:String = "",showWarn:Boolean=true):void {
    if (name) _setFramesFromCache(name, showWarn);
    this._isPlaying = true;
    this.index = (start is String) ? _getFrameByLabel(start) : start;
    this.loop = loop;
    this._actionName = name;
    _isReverse = wrapMode == WRAP_REVERSE;
    if (this._frames && this.interval > 0) {
        timerLoop(this.interval, this, _frameLoop, null, true, true);
    }
}

start參數(shù)支持幀標(biāo)簽來控制播放口叙。
loop參數(shù)默認(rèn)是true炼绘,即循環(huán)播放
關(guān)于name參數(shù),注釋是這樣寫的:動畫模板在動畫模版緩存池中的key妄田,也可認(rèn)為是動畫名稱俺亮。如果name為空驮捍,則播放當(dāng)前動畫序列幀;如果不為空脚曾,則在動畫模版緩存池中尋找key值為name的動畫模版东且,如果存在則用此動畫模版初始化當(dāng)前序列幀并播放,如果不存在本讥,則仍然播放當(dāng)前動畫序列幀珊泳;如果沒有當(dāng)前動畫的幀數(shù)據(jù),則不播放拷沸,但該實(shí)例仍然處于播放狀態(tài)色查。

//創(chuàng)建一個(gè)Animation實(shí)例
var tl:Animation = new Animation();
//加載動畫文件
tl.loadAnimation("TimeLine.ani");
//添加到舞臺
Laya.stage.addChild(tl);
//播放Animation動畫
tl.play();

//創(chuàng)建一個(gè)新的Animation實(shí)例
var tl2:Animation = new Animation();
//加載動畫文件
tl2.loadAnimation("TimeLine.ani");
//添加到舞臺
Laya.stage.addChild(tl2);
//播放Animation動畫的pivot動畫
tl2.play(0, true, "pivot");
//動畫的顯示位置
tl2.pos(300,0);

上面的代碼,就是IDE制作的ani中堵漱,有兩個(gè)動畫综慎,可以通過name參數(shù)去選擇播放,缺省播放第一個(gè)動畫勤庐。


image.png

7.在loadAnimation方式中示惊,牽涉到_loadAnimationData方法,進(jìn)而使用了_parseGraphicAnimation方法愉镰。這就牽涉到GraphicAnimation類了米罚。

三、幀動畫的數(shù)據(jù)解析

下面這三個(gè)類丈探,針對IDE制作的動畫及動效模板進(jìn)行解析录择。比較復(fù)雜,暫時(shí)不做閱讀碗降。

1.FrameAnimation extends AnimationPlayerBase
關(guān)鍵幀動畫播放類

2.EffectAnimation extends FrameAnimation
動效模板隘竭。用于為指定目標(biāo)對象添加動畫效果。每個(gè)動效有唯一的目標(biāo)對象讼渊,而同一個(gè)對象可以添加多個(gè)動效动看。 當(dāng)一個(gè)動效開始播放時(shí),其他動效會自動停止播放

3.GraphicAnimation extend FrameAnimation
就是IDE創(chuàng)建的時(shí)間軸動畫


image.png
四爪幻、IDE動畫編輯器使用

參考時(shí)間軸動畫編輯器詳解菱皆,介紹很詳細(xì),以下記錄自己的使用經(jīng)驗(yàn)
1.選中左側(cè)屬性挨稿,可以設(shè)置相應(yīng)的緩動函數(shù)類型和標(biāo)簽

image.png

image.png

image.png

當(dāng)設(shè)置標(biāo)簽后仇轻,設(shè)置標(biāo)簽的幀會出現(xiàn)紅色圓點(diǎn)∧谈剩可以在項(xiàng)目中篷店,通過標(biāo)簽名用代碼對該幀進(jìn)行操作。

2.多個(gè)節(jié)點(diǎn)臭家,也就是分層動畫船庇,比如上圖中的GraphicNode2,Graphic3
注意官方示例中所說吭产,拖拽一個(gè)新的組件到場景。即會自動新增一個(gè)節(jié)點(diǎn)層鸭轮,剛開始我很困惑怎么增加新節(jié)點(diǎn)層臣淤。
另外,注意窃爷,時(shí)間軸動畫的負(fù)坐標(biāo)區(qū)域內(nèi)邑蒋,無法觸發(fā)點(diǎn)擊事件,如果需要用到點(diǎn)擊事件交互按厘,則動畫的X與Y必須位于正坐標(biāo)區(qū)域医吊,也就是十字紅線交叉的右下區(qū)域。

3.設(shè)置關(guān)鍵幀坐標(biāo)時(shí)TIPS
如果要改坐標(biāo)逮京,先改后面的卿堂。如果從前往后改,后面的坐標(biāo)動了懒棉,前一個(gè)會自動變成中間值 草描。

4.我想做一個(gè)光斑繞扇形移動的動畫,如下圖策严,圓弧段可以逐幀移動穗慕,而兩個(gè)直線區(qū)域則可以使用補(bǔ)間動畫,補(bǔ)間動畫起始點(diǎn)和結(jié)束點(diǎn)妻导,相隔的幀數(shù)逛绵,可以大概估算一下,保證每幀的移動速度和圓弧段每幀移動速度差不多就行倔韭。


image.png

這里有個(gè)方便的技巧就是术浪,先建一個(gè)測試動畫,把光斑都放到同一幀寿酌,否則無法直觀看到全部的運(yùn)動軌跡胰苏。當(dāng)然,把背景圖片也放進(jìn)去份名,位置更精確。然后再建正式動畫妓美,每一幀的位置就可以參考測試動畫里的坐標(biāo)了僵腺。

5.Animation中是可以使用遮罩的


image.png

如圖,這個(gè)動畫顯示的不是光斑壶栋,而是光條辰如。


image.png

image.png

方法就是,在Animation里拖一個(gè)Sprite贵试,設(shè)置renderType為mask琉兜。然后在里面用Lines畫出軌跡凯正,同時(shí)設(shè)置線寬。當(dāng)然越寬豌蟋,光條露出來的就越粗了廊散。
image.png
五、動效模板

參考創(chuàng)建動效模板(EffectAnimation)

image.png

EffectAnimation extends FrameAnimation
動效模板梧疲。用于為指定目標(biāo)對象添加動畫效果允睹。每個(gè)動效有唯一的目標(biāo)對象,而同一個(gè)對象可以添加多個(gè)動效幌氮。 當(dāng)一個(gè)動效開始播放時(shí)缭受,其他動效會自動停止播放

動效模板是基于時(shí)間軸的動畫效果,通過預(yù)設(shè)動畫效果该互,然后把效果附加給某個(gè)組件米者。使得組件無需編碼,卻輕松實(shí)現(xiàn)與編碼相同的動畫效果宇智。動效模板不能獨(dú)立顯示蔓搞,僅可作為動效模板讓UI頁面中的組件獲得動畫效果。

1.按照上述示例普筹,發(fā)現(xiàn)綁定一個(gè)組件后败明,我的組件坐標(biāo)會改變?yōu)閯有0宓淖鴺?biāo)
參考關(guān)于動效模板使用后改變了原來組件的坐標(biāo)問題

刪除x,y

2.希望某個(gè)動效完成后,做一些事情
參考監(jiān)聽動效動畫的COMPLETE(播放完成)事件

在var里取名太防,即可進(jìn)行代碼偵聽

事件目前只有這幾個(gè)妻顶,暫時(shí)不支持自定義事件。

3.參考動畫模板中蜒车,要求到拖入一張圖讳嘱,然后制作一個(gè)動畫,這張圖是隨便都可以的嗎
資源目錄中png和jpg格式的都可以

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酿愧,一起剝皮案震驚了整個(gè)濱河市谈撒,隨后出現(xiàn)的幾起案子录煤,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矛纹,死亡現(xiàn)場離奇詭異,居然都是意外死亡瞳购,警方通過查閱死者的電腦和手機(jī)褪尝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來基括,“玉大人颜懊,你說我怎么就攤上這事。” “怎么了河爹?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵匠璧,是天一觀的道長。 經(jīng)常有香客問我咸这,道長夷恍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任炊苫,我火速辦了婚禮裁厅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘侨艾。我一直安慰自己执虹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布唠梨。 她就那樣靜靜地躺著袋励,像睡著了一般。 火紅的嫁衣襯著肌膚如雪当叭。 梳的紋絲不亂的頭發(fā)上茬故,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天,我揣著相機(jī)與錄音蚁鳖,去河邊找鬼磺芭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛醉箕,可吹牛的內(nèi)容都是我干的钾腺。 我是一名探鬼主播,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼讥裤,長吁一口氣:“原來是場噩夢啊……” “哼放棒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起己英,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤间螟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后损肛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厢破,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年治拿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摩泪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡忍啤,死狀恐怖加勤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情同波,我是刑警寧澤鳄梅,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站未檩,受9級特大地震影響戴尸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冤狡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一孙蒙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悲雳,春花似錦挎峦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晴楔,卻和暖如春顿苇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背税弃。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工纪岁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人则果。 一個(gè)月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓幔翰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親短条。 傳聞我的和親對象是個(gè)殘疾皇子导匣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 用到的組件 1、通過CocoaPods安裝 2茸时、第三方類庫安裝 3贡定、第三方服務(wù) 友盟社會化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 14,627評論 1 180
  • 作為國企新入職的一名被欺負(fù)小菜鳥,請求你把吃包子看為一項(xiàng)崇高的事業(yè)來完成吧可都! 哈哈\\(^o^)/ yeah
    開心的高毛毛閱讀 116評論 0 0
  • 《寒九周談》 修由此行究猶書缓待, 注見桃花開繁朵。 對望江城舊相愁渠牲, 佐取紅塵凡塞托旋炒。 十里畫墨黑宿主, 五卷寒興飛...
    春城怡景閱讀 235評論 2 16