年底了,接个大活儿,做一个回顾公司五年发展的总结ppt,要求做成H5网页
公司想做個五年總結(jié)
這不快年底了么,公司高層打算把這五年的發(fā)展歷程做一次回顧巡禮,一方面宣揚一下公司文化,另一方面歌頌一下公司這五年來取得的輝煌成就,單純的做個海報,寫個公眾號文章,或整個傳統(tǒng)ppt在內(nèi)部宣講,再剪個視頻啥的已經(jīng)無法滿足公司想眾樂樂的強烈情感了。
于是想做一個交互性良好、內(nèi)容表達形式多樣、章節(jié)清晰、條理分明、易于傳播的“ppt”,于是在公司千人大群里號召,有沒有誰能做的,問了好幾次,最后只有我應(yīng)下了這個大活兒。
最后我與一位主要負責這件事的領(lǐng)導(我稱為帶頭大哥)和一位UI小姐姐臨時組成了一個小隊,來完成這項任務(wù)。
(在線觀看地址,可以先看看效果。記得手指或者鼠標,向上滑動來播放)
很快就確定了中心思想,并設(shè)計了一套。。。。對聯(lián)?
帶頭大哥沒過幾日就發(fā)我一個文檔,上面寫了對仗工整,思想明確的“對聯(lián)”
- 我:哇撒~,領(lǐng)導,這寫的很好嘛~,這每一頁不做個動畫都說不過去啊。
- 領(lǐng)導:對,就打算這么做。
- 我:哈哈哈哈,收到,那么具體做成什么樣呢?
- 領(lǐng)導:em~,我已經(jīng)安排UI小姐姐開始設(shè)計了,過一陣就能出圖。
- 我:哦哦哦,好的~
領(lǐng)會精神的設(shè)計小姐姐就開始陸續(xù)出圖了~~~
- 領(lǐng)導:阿強,圖做好了,你看一下。
- 我:ok,哇偶這圖可以啊。
- UI小姐姐:有什么問題,需要切圖啥的盡管跟我說。
- 我:好的好的。
- 領(lǐng)導:阿強,那么我們開始研究如何做吧,要求是要做成H5,這樣可以方便分享傳閱,而且時間我們只有五天,我們要盡快了。
- 我:五天???做不完咋辦
- 領(lǐng)導:你知道的,deedline不是我定的,而且這是👆面看中的親兒子項目,獻禮用的,所以。。。
- 我:懂了,我搏一把,目前來看用游戲引擎最合適,畢竟畫面表現(xiàn)這塊,用引擎更好一點。
- 領(lǐng)導:可以,具體設(shè)計方面到時我們再一起商量怎么做,開發(fā)這塊需要的話,我也可以參與進來,畢竟我也接觸過白鷺引擎,對了,你打算用啥寫?
- 我:cocos creater
- 領(lǐng)導:嗯嗯,沒問題,有什么我能幫忙的盡管跟我說,最后能做出來就行
- 我:好的,收到。
于是我做了一個工具
so,時間這么緊,而且做不完可能會有不小的后果,em~~~~,并且這件事也不是著急干就能干完的,我需要冷靜的想一個辦法,我忽然想到《代碼整潔之道》中好像說過,具體記不清,大體意思是:“越是想快,就要寫好代碼”。
em~~~,好的,那么我拿出幾天設(shè)計一個工具吧,不需要多么成熟,只要能夠滿足容易上手,可以批量制作就行,這樣就能夠?qū)崿F(xiàn)人手的增加,效率也會提高的局面,到時完成就變得很有戲了,就這么辦。
于是我用了兩三天的時間做出了這個工具,并做了一個demo給到了帶頭大哥,他表示ok,還可以,能接受,而且經(jīng)過我的指導,他也可以參與進來了,于是我們就開始“愉快地”批量的制作了。
工具的開發(fā)思路
我總希望用最簡單的話語,描述一件事,我比較喜歡簡單,那么我們就用簡單的方式把我的設(shè)計講講。
通過鼠標或觸摸滑動,推進動畫進程
視頻可以快進,倒退,僅僅通過撥動進度條或者滑動屏幕即可,我喜歡這種交互,那就做成這樣,舒服。 首先我不想做成靜態(tài)資源那種的,比如視頻,gif之類的,這種是沒有“生命”的,只能稱之為“物質(zhì)”,我簡單用“陰”代指,我所需要是基于物質(zhì)所煥發(fā)同時也可以創(chuàng)造物質(zhì)的的“生命,心靈”,我稱他為陽。說ta是“活”的有點過,就是說可以交互,可以整合再利用,隨時可以通過ta創(chuàng)建視頻,gif之類的靜態(tài)資源,豈不妙哉。
設(shè)計好個體,非常關(guān)鍵
我希望設(shè)計出一系列獨立個體,可以很好的串聯(lián)起整個邏輯,它具備了基本的功能,同時又具備了擴展的能力,可互相聯(lián)結(jié),又彼此獨立,目前有兩個主要的個體,一個是單位個體entity,另一個是動作個體recation
entity大體應(yīng)該具備以下行為:
- 描述自身運行的周期: lenPercent和startPercent
- 生命周期函數(shù)
- 開始:live
- 渲染:process
- 結(jié)束:end
- 可以裝載其他個體的能力:entityArr
- 組成單位為:entity
- 執(zhí)行動作的集合:recationArr
- 組成單位為:recation,
recation大體應(yīng)該具備以下行為:
- 描述自身運行的周期:start和end
- 執(zhí)行的動作:action()
那么個體設(shè)計好了,圍繞個體所展開的邏輯,就順理成章了。
代碼如下:
export default cc.Class({extends: cc.Component,properties: {lenPercent: cc.Float,startPercent: cc.Float,isAutoStart: cc.Boolean,entityArr: {default: [],type: cc.Node}},//externalDuration:外部時間(父節(jié)點傳過來的時間),由父節(jié)點決定//internalDuration:自己內(nèi)部定的時間,有自己決定,//為什么要區(qū)分兩個呢?由于外部應(yīng)該只能確定我的播放時間,不應(yīng)該決定我的播放速率,而后者應(yīng)該有個體自身決定,//startTime和endTime:由父節(jié)點指定的開始和結(jié)束時間,(根據(jù)父節(jié)點的世界定的‘外部時間’!!!)//timeLine-表示時間到哪了,(根據(jù)父節(jié)點的世界定的‘外部時間’!!!)//totaTime-表示我在父節(jié)點應(yīng)該播放的總時長,(根據(jù)父節(jié)點的世界定的‘外部時間’!!!)//progressValue就是通過父節(jié)點傳過來的timeLine,totaTime,timeLine得出我處于的播放進度百分比//相應(yīng)的往自己的子節(jié)點傳的就得參照自己的ctor() {this.isLive = false;this.startTime = undefined;this.endTime = undefined;this.internalDuration = 0;//個體內(nèi)部的時長this.externalDuration = 0;//個體相對父級的時長this.progressValue = 0;this.entryData = [];this.recationArr = [];this.startPosition = cc.v2();this.entityArrEx = [];},// LIFE-CYCLE CALLBACKS:start() {this.startPosition = this.node.position;},onLoad() {this.node.comName = this.__classname__;this.internalDuration = this.node.getContentSize().height;//防止設(shè)置的時間太長,強制設(shè)置為剩余的時長if (this.lenPercent + this.startPercent > 1) {this.lenPercent = 1 - this.startPercent;}if (this.isAutoStart) {this.startPercent += Math.abs((this.node.position.y / this.node.parent.getContentSize().height));}},onEnable() {let self = this;if (this.entityArr.length) {this.entityArrEx = this.entityArr.map((item, index) => {let entity = item.getComponent(item._name);if (entity.isAutoStart) {}this.entryData.push(entity.initData({startTime: this.getStarTime(entity.startPercent),totaTime: self.internalDuration,}));return entity;});}},//業(yè)務(wù)接口getStarTime(value) {if (value <= 1) {return value * this.internalDuration} else {return value}},initData({ totaTime, startTime }) {this.startTime = startTime;this.externalDuration = this.lenPercent <= 1 ? totaTime * this.lenPercent : this.lenPercent;//結(jié)束時間最大只能是父類節(jié)點結(jié)束時間//因為父節(jié)點結(jié)束,子節(jié)點也必須結(jié)束this.endTime = Math.min(totaTime, this.startTime + this.externalDuration);return {startTime: this.startTime,internalDuration: this.internalDuration,endTime: this.endTime}},getCurrentTime(percent) {return (this.startTime + (percent <= 1 ? this.externalDuration * percent : percent));},live() {this.isLive = true;},calcProgress() {this.progressValue = (this.timeLine - this.startTime) / this.externalDuration;},calcReactionProgress({ start, end }) {start = (start <= 1) ? this.internalDuration * start : start;end = (end <= 1) ? this.internalDuration * end : end;return Math.min((this.progressValue * this.internalDuration - start) / (end - start), 1);},process({ timeLine }) {this.timeLine = timeLine;this.calcProgress();this.internalTimeLine = this.progressValue * this.internalDuration;let actionArr = this.recationArr.filter((item) => {if (item) {let isOk = (timeLine > this.getCurrentTime(item.start) &&timeLine <= this.getCurrentTime(item.end)) ||(!item.start && !item.end)if (isOk) {item.isAction = true} else {if (item.isAction) {item.action(this.calcActionData(item, true))}item.isAction = false}return isOk;}});actionArr.forEach((item) => {item.action(this.calcActionData(item));});},update() {let self = this;this.actionEntityArr = this.entityArrEx.filter((entity) => {if ((self.internalTimeLine) > entity.startTime && self.internalTimeLine <= entity.endTime) {if (!entity.isLive) {entity.live();}entity.process({timeLine: self.progressValue * self.internalDuration,});return true;} else {if (entity.isLive) {entity.end();}}return false;});},calcActionData(item, isEnd) {let params = {};let actionLen = (item.end - item.start) || 1;let progress;progress = Math.min((this.progressValue - item.start) / actionLen, 1);if (isEnd) {let isEndForce = window.GLOBAL.dir > 0;let isEndForceStart = window.GLOBAL.dir < 0;if (isEndForce) {progress = 1} else if (isEndForceStart) {progress = 0}params = {isEndForce: isEndForce,isEndForceStart: isEndForceStart}}params = {actionLen,progress,...params,...item}return params;},end() {this.isLive = false;//如果滑動非常快,并且是快進而非后退,那么就要直接強行設(shè)置反饋為結(jié)束// if (window.GLOBAL.dir > 0) {// }this.recationArr.forEach(item => {if (item.isAction) {item.isAction = falseitem.action(this.calcActionData(item, true))}});}, });復制代碼整體思路簡單說
- 就是設(shè)置一個進度條,通過觸摸屏幕進行前進和后退。
- 設(shè)置每一part的時間占比,然后串聯(lián)起來。
- 每一個part內(nèi)部,也設(shè)置內(nèi)部節(jié)點的運動的事件占比,以及具體做什么運動。
- 然后根據(jù)定時循環(huán),判斷當前時刻應(yīng)該執(zhí)行節(jié)點的是哪個,執(zhí)行的節(jié)點該執(zhí)行的運動是哪個
就這么簡單。
這個思路完全可以使用在dom上,完全可以用react和vue實現(xiàn),我會陸續(xù)重構(gòu)完畢。
我跟領(lǐng)導就開始設(shè)計怎么做了
開場
-
領(lǐng)導:阿強,這個就是我們項目的開場。
- 第一張就是首頁圖,然后過一會自動轉(zhuǎn)場。
- 第二張就是過場之后顯示的。
-
我:哦哦,懂了,話說,怎么轉(zhuǎn)場呢?
-
領(lǐng)導:看到小飛機沒有~
-
就這個。
-
還有第二頁的這個。
-
(A):第一頁上來,左下角一個人坐著飛機向上飛,然后小飛機往右上角飛,飛離出去之后,開始轉(zhuǎn)場到二張。
-
(B)然后第二頁左下飛入這個小飛機,飛到中心處,也就是圖片上的位置,那么開場part就ok了。)
-
-
我:ok,明白了,開整。
實現(xiàn)方式:
A實現(xiàn):
目標就是讓這個節(jié)點移動一段距離停下來,那么寫一個腳本plane0_1,上來就執(zhí)行一個移動一段距離的動作。
import entity from '../../base/entity'; cc.Class({extends: entity,properties: {},// LIFE-CYCLE CALLBACKS:onLoad() {this._super();let self = this;// 就是上來,就執(zhí)行一個運動,moveBy就是一段時間,移動移動距離的動畫apivar action = cc.moveBy(1, cc.v2(this.node.getContentSize().width + 100, 200))// 執(zhí)行動作this.node.runAction(action);}, });復制代碼掛載到節(jié)點上就可以了。
這里簡單介紹一下,我設(shè)置了幾個參數(shù):
- lenPercent:就是節(jié)點運動的總時長
- startPercent:就是運動的開始時刻
- isAutoStart:就是自動啟動,無視startPercent的設(shè)置
- entityArr:就是復制管理的節(jié)點,這樣自己的運動周期內(nèi)就能操作其關(guān)聯(lián)的節(jié)點的運動。
B實現(xiàn):主要就是實現(xiàn)這個節(jié)點移動飛行
那么根據(jù)上面描述的思路,我們不難實現(xiàn)這個小飛機的移動,無非就是設(shè)置這個小飛機在這個part里的開始時刻是多少,運動多久,運動到哪,只要把這些定好,動畫自動產(chǎn)生。
那么開發(fā)腳本
import entity from '../../base/entity'; cc.Class({extends: entity,properties: {plane: cc.Node},// LIFE-CYCLE CALLBACKS:onLoad() {this._super();let self = this;// 向右上角移動一段距離var action = cc.moveBy(1, cc.v2(this.node.getContentSize().width + 500, 500))// spawn是同時執(zhí)行運動的函數(shù),目的是讓moveBy運動結(jié)合一個縮小的運動,這樣,有種越發(fā)越遠,又越小的視覺感。let action2 = cc.spawn(action, cc.scaleTo(1, 2))// 執(zhí)行動作this.node.runAction(cc.sequence(cc.delayTime(1), action2, cc.callFunc(() => {self.node.active = false;self.node.parent.active = false;self.plane.runAction(cc.moveTo(1, cc.v2(0, 0)))})));}, });復制代碼那么下面整體實現(xiàn),基本都是依靠上面這些思路,實現(xiàn)的,單純的開始套就能實現(xiàn)下面的動畫了。 是不是很神奇,這套思路,完全可以套用到react和vue上。
-
整好了,領(lǐng)導~,看下效果
-
領(lǐng)導:行,可以,就這樣。
part1
-
重返這五年,重溫那歲月
-
領(lǐng)導:這張呢~
-
我:坐飛機的小女孩往上飛出去,做小角的男人飛入畫面
-
領(lǐng)導:差不多,不過坐小飛機的小女孩這塊,應(yīng)該再豐富一點。
- 記得我們剛才說的那個小飛機沒,這個小女孩飛的時候,漸漸的變小,有種往遠飛的感覺,然后變成小飛機飛走~
-
我:哦哦哦,懂了,開整
-
整好了,領(lǐng)導~,看下效果
-
-
領(lǐng)導:行,可以,就這樣。
part2
- 成長多措舉,管理提格局
- 工作造氛圍,企學見雛形
-
我:這個要做成啥樣?
-
領(lǐng)導:入場就是從右邊緩緩進來,還有看到這個沒
-
這些圓片一點一點的滑入屏幕,然后屏幕出現(xiàn)內(nèi)容
-
這張圖
- 就是屏幕上一點一點出現(xiàn)內(nèi)容,然后人物一點一點入畫。
-
-
我:懂了,開整
-
整好了,領(lǐng)導~,看下效果
-
-
領(lǐng)導:對,是這樣。
part3
- 發(fā)展聚人才,規(guī)模逐壯大
- 搜索尋突破,拓展創(chuàng)業(yè)務(wù)
- 領(lǐng)導:這個主要想表達的就是公司不斷的壯大,業(yè)務(wù)上不斷的突破,所以要有種過程感,你看著發(fā)揮吧
- 我:收到,我試試
-
整好了,領(lǐng)導~,看下效果
-
- 領(lǐng)導:嗯,很不錯,可以可以,有過程的畫面感。
- 日歷還能動啊,而且日歷動的同時,后面的背景一點一點的顯示,也寓示了我們的辦公樓越來越大,可以,有細節(jié),不錯。
- 過場加入了云彩變大,切換很自然嘛。
part4
-
那年啟征程,改變從此始
-
領(lǐng)導:這個該咋設(shè)計呢?你看飛機這么多,我們能讓這些飛機各飛各的么?
-
我:可以啊,我試試
-
整好了,領(lǐng)導~,看下效果
-
-
領(lǐng)導:可以的,就這樣吧。
part5
- 種得梧桐樹,鳳凰自然來
- 領(lǐng)導:這個柱狀圖能不能表現(xiàn)出一點一點增長的效果,還有向上箭頭能不能也可以有個升的過程
-
還有這個拿筆的人物
- 可不可以有種書寫感,就是表現(xiàn)出在寫字
-
- 我:哦哦哦,我試試,應(yīng)該可以,針對這些情況,我再豐富幾種表現(xiàn)手段
-
整好了,領(lǐng)導~,看下效果
-
- 領(lǐng)導:嗯,可以,就是這效果。
part6
- 全方位服務(wù),碼農(nóng)心無騖
- 創(chuàng)新謀發(fā)展,突破新技術(shù)
- 領(lǐng)導:這就可以自由發(fā)揮了,用一個合理的方式一點一點介紹就好。
- 我:懂,開整
-
整好了,領(lǐng)導~,看下效果
-
- 領(lǐng)導:嗯,很不錯嘛,有ppt的感覺,挺好的
- 我:哈哈哈,確實有點。
part7
- 環(huán)境不斷好,員工感幸福
- 乘勢迎挑戰(zhàn),賦能于行業(yè)
-
領(lǐng)導:第一張就是簡單的顯隱就可以,主要是第二張的這個
- 這個,我跟UI小姐姐說了,希望做成一個列表,但小姐姐做成了這種,那么就需要滾動了。
-
我:就像滾動頁面那樣,哦哦哦,我明白了,開整。
-
整好了,領(lǐng)導~,看下效果
-
-
領(lǐng)導:行,可以的,就這樣。
part8
- 磨礪積能力,自研得碩果
-
領(lǐng)導:阿強,這個主要是表現(xiàn)我們?nèi)サ某删?#xff0c;我們僅僅把文字凸顯出來就好,其他就不要求了
- 但,我覺得第一幅圖,還是可以做點文章的,他表示我們獲得的證書,你看看能不能實現(xiàn),物理下落,然后一本本摞起來的效果
-
我:哈哈哈,好的,我試試,效果我盡量做,可能物理效果沒那么像,但摞起來的效果肯定是有的。
-
領(lǐng)導:可以,你試試
-
我:好的,開整。
-
整好了,領(lǐng)導~,看下效果
-
-
領(lǐng)導:辛苦了,阿強,再加把勁,我們要成功了。
-
我:好的~~~下一個就是結(jié)尾了吧,加油~
尾聲
- 逆境砥礪行,收入節(jié)節(jié)高
- 領(lǐng)導:阿強這個結(jié)尾,我們收好,我們要有種意境,這樣就有感覺,你能懂么
- 我:我懂你
- 領(lǐng)導:你看奧第一幅和第二幅區(qū)別,是一個沒有河水,一個有河水,還有就是一個有沒破曉,一個有日出
- 你看你能銜接好,這可是一個艱巨的任務(wù),干完這個我們就勝利了
- 我:好的領(lǐng)導,我一定完成任務(wù)
-
many hours later
-
可算整好了,我的大哥~,效果我是盡力了。
-
- 領(lǐng)導:干的漂亮,阿強,有意境了,非常不錯,辛苦了。
- 我:嘿嘿,馬馬虎虎,我盡力了,我打包好就上線吧。
- 領(lǐng)導:好的好的,辛苦了。
這就是在線預覽地址,可以看看效果。
結(jié)尾
目前項目僅僅用了5天時間就出來了個雛形,還很粗糙,很多地方可以進一步的優(yōu)化。
這僅僅是一個開始,未來,我會使用react或者vue3,整一個lowcode制作工具,這樣就可以更加的方便制作了。
然后開源,敬請期待。
有問題隨時交流,我建立一個小清晰qq群,叫“閑D島”,技術(shù)問答群,有問必答,有興趣可以加群號:551406017
題外話
有一說一,我比較低調(diào),一般出風頭的事兒,我是沒啥想法的,主要是我覺得爭名逐利的畫面太尷尬,我來不了這個,但也不知我那天是怎么了,當群里問了好幾次都沒人回應(yīng),我就來了點脾氣,即然沒誰上,那我試試吧。就這樣我接下了這個任務(wù),現(xiàn)在再想,可能就是因為這點脾氣,我才敢去做的,也許有點莽了,如果沒做成呢?哈哈哈,那就不能想了,還好我實現(xiàn)了,我讓這個脾氣變得更像勇氣了,有時候真不妨大膽一點,覺得自己可以,那就試一試,真沒準行呢,別怕輸,輸丟什么人,怕才丟人呢。
總結(jié)
以上是生活随笔為你收集整理的年底了,接个大活儿,做一个回顾公司五年发展的总结ppt,要求做成H5网页的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 记一次Android全流程开发体验经历以
- 下一篇: 2018VR创意创新创业大赛探索VR技术