導(dǎo)數(shù),微積分靠柑,牛頓運動學(xué)制作創(chuàng)意地圖

大前端時代下寨辩,面向組件,面向數(shù)據(jù)編程已家常便飯歼冰,但是作為一個合格的程序員靡狞,優(yōu)秀的邏輯思維和抽象能力是其最基本的素質(zhì)。代碼只是實現(xiàn)過程和編程功底的體現(xiàn)隔嫡,更重要的是分析問題甸怕,建模實力甘穿,解決問題,才能實現(xiàn)技術(shù)創(chuàng)新梢杭,引領(lǐng)業(yè)務(wù)温兼,改變世界

點擊查看本文的第一個案例

一個優(yōu)秀的程序員應(yīng)該做到:

1. 觀察歸納需求,抽象需求

2. 設(shè)計算法將需求數(shù)學(xué)化武契,建立合理的數(shù)學(xué)模型

3. 扎實的編程功底實現(xiàn)模型

我們首先歸納的應(yīng)該有以下的細節(jié):

1. 整個頁面的動效交互只有滾動條觸發(fā)

2. 兩點之間是任意曲線募判,曲線的運動學(xué)是整個曲線方程的子集軌跡,也就是局部曲線

3. 由于滾動條有上下滾動兩個方向吝羞,所以曲線的運動軌跡的長度隨滾動條的高度成正比兰伤,即向下滾動,軌跡變長钧排,向上滾動敦腔,軌跡變短,注意一點恨溜,軌跡長度的變化方向符衔,和原曲線的方向一致

4. 飛機沿著曲線的運動軌跡而做曲線運動,注意一點糟袁,由于飛機是svg圖片判族,而其運動軌跡是任意曲線,那么飛機的方向也必須跟隨軌跡運動而實時變化项戴,這一點非常重要形帮!

5. 飛機在兩點之間運動時,在該曲線的起點到1/2長度之間周叮,飛機逐漸變大辩撑,在運動到超過1/2長度和自身長度之間,飛機又逐漸變小

6. 在曲線運動過程中仿耽,整個地圖也發(fā)生運動合冀,且地圖的運動軌跡和當前時刻曲線的運動方向一致

7. 在滾動過程中,當左側(cè)圖文面板里出現(xiàn)圖片项贺,那么以飛機為三角形定點君躺,左側(cè)圖片的上下兩個點為三角形底邊,作一個三角形光束照射在圖片上开缎,并且隨著底邊點的位置改變定點角度也隨著變化

以上細節(jié)棕叫,是一個程序員最基本的觀察力和對需求的歸納能力,那么接下來奕删,開始動手編程谍珊?那是新手,接下來要做的應(yīng)該是逐一分析技術(shù)算法細節(jié),也是培養(yǎng)我們的建模能力

下面開始算法原理的分析:

1. 前端技術(shù)棧很明顯砌滞,使用原生js和canvas技術(shù)就可以實現(xiàn)侮邀,這一點沒什么可以說的

2. 曲線的制作可以利用三次貝塞爾方程(一切的計算都源于此方程)

三次貝塞爾曲線的參數(shù)方程

通過此方程,我們可以方便的求其偏導(dǎo)數(shù)以及任意時刻t對應(yīng)的x和y值

3. 兩點間一曲線贝润,把一條曲線和4個點(繪制三次貝塞爾)抽象成一個類绊茧,這非常容易想到,而這個類里應(yīng)封裝基本的繪制方法打掘,包含曲線华畏、圓形點、飛機圖形尊蚁、三角形等亡笑,還應(yīng)封裝計算方法,包含根據(jù)任意時刻t計算相應(yīng)的x和y值横朋、根據(jù)任意x或y值反解出曲線對應(yīng)的t值仑乌、求x和y的偏導(dǎo)數(shù)、求曲線上任意一點的斜率琴锭、求曲線的總長度

以上的分析依然很簡單晰甚,只不過是oop和canvas的api的使用,接下來實際說明為什么需要封裝這些計算方法

4. 繪制局部貝塞爾曲線:

我們知道使用canvas的api里bezierCurveTo(p0,p1,p2,p3)很容易畫出一條完整的貝塞爾曲線决帖,但是我們需要模擬的運動學(xué)厕九,是沿著曲線做曲線運動,也就是需要繪制局部曲線地回,而canvas是沒有給我們提供繪制任意局部曲線的api的扁远,所以單純依賴api是走不通的,我們需要從本質(zhì)原理出發(fā)推理

我們知道兩點可以組成一條直線刻像,那么曲線呢穿香?而任意一條線上有多少個點?不妨假設(shè)有n個點绎速,那么如果這n個點的坐標不是線性的,那么將這n個點連接起來焙蚓,就是一條完整的曲線纹冤,如果這n個點的坐標滿足貝塞爾方程,那么組合起來就是一條完整的貝塞爾曲線

分析到這里购公,我們可以抽象出我們只要選擇m個點(0=<m<=n)萌京,將這m個點連接起來,就構(gòu)成了局部貝塞爾曲線(請思考為什么不只選取運動起點和運動終點來連線)

而新問題緊接著產(chǎn)生宏浩,我們設(shè)滾動條滾動的距離為a知残,怎么去計算出a所對應(yīng)的方程的x和y?

因為我們?yōu)g覽器的屏幕是笛卡爾坐標系比庄,我們繪制任意一個點需要知道點的x坐標和y坐標求妹,所以我們很容易想到不妨用a去映射方程終點p3對應(yīng)的x乏盐,那么我們只需要求出p3的y值即可完成終點的繪制。觀察方程制恍,我們不能直接利用x去求y父能,需要先求出p3.x對應(yīng)的t值,才能用t去計算p3.y

已知任意時刻t的方程净神,P0何吝,P1,P2鹃唯,P3為四個點爱榕,其中P0和P3是起點和終點,P1和P2是控制點

曲線方程

我們已知曲線終點的Px坡慌,求Py黔酥,那么兩邊除以t的三次方,整理得:

化簡一

設(shè) m = (1 - t) / t八匠,即可以整理出:

化簡二

我們知道這是一個標準的三次方程絮爷,利用三次求根公式可以解出m進而求出t,那么帶入t和另外三個點的y值就可以求出p3的y值

但是這并不是一個非常好的做法梨树,因為考慮我們繪制的是任意曲線坑夯,方程圖像如果存在以下這種情況

一對多的情況

那么我們很難控制曲線到底應(yīng)該畫到第一個y值,還是第二個y值抡四,所以綜上分析柜蜈,a去映射x求t來解y,會存在多解影響笛卡爾坐標繪制指巡,故而正確的做法應(yīng)該是用a去映射t淑履,用t來解出x和y

那么問題繼而轉(zhuǎn)化為,a怎么去映射t藻雪?

我們可以容易的想到如果已知曲線的總長度L秘噪,用a和L的比率去計算局部dl,我們假設(shè)長度為L的曲線對應(yīng)可視高度為H的值(當盒子完全被滾動條卷入勉耀,也就證明線走完了)指煎,可以得到dl = L / H * a,則此時此刻的t = dl / L (t 屬于[0便斥,1])

那么問題就轉(zhuǎn)化為需要先求出任意曲線的長度L至壤?

我們知道路程 = 速度 * 時間,基于微積分的思想枢纠,我們假設(shè)某個很小的時刻dt像街,存在速度dv,那么ds = dv * dt,最后我們對所有dt對應(yīng)的ds進行求和镰绎,可以逼近曲線的總長度L(我們假設(shè)將曲線S劃分為N段)

問題即又轉(zhuǎn)化為怎么求速度脓斩?(這里指的是合速度)

很明顯,我們需要對曲線方程對t進行求導(dǎo)跟狱,即得到其速度的方程式

求導(dǎo)過程非常簡單(請復(fù)習(xí)高中復(fù)合函數(shù)求導(dǎo))

速度方程

我們帶入t求出兩個方向的速度俭厚,很顯然,一個是沿著x方向的速度vx驶臊,另一個是沿著y方向的速度vy挪挤,我們需要計算出二者產(chǎn)生的合力的速度v即可

根據(jù)平行四邊形法則,我們知道v = (vx * vx + vy * vy) ^ 1/2关翎,現(xiàn)在我們終于可以計算出曲線的長度L = ∑ v * dt扛门,而a和H已知(單純的網(wǎng)頁dom計算,不題)纵寝,我們就可以得到dl = L / H * a论寨,最后得到t = dl / L,完成了a和t的映射關(guān)系

現(xiàn)在我們用a映射出t爽茴,并且可以保證t在0到1之間葬凳,根據(jù)t解出真正的x和y值,至此室奏,我們終于可以畫出局部曲線了

5. 局部曲線長度的動效變化:

當我們建立如何畫局部曲線后火焰,將要解決隨著滾動條向上或向下滾動時候,局部曲線的長度變化過程‰誓現(xiàn)在我們已經(jīng)得到任一點的dt和該dt對應(yīng)的x和y值昌简,很顯然想到利用canvas的LineTo(x, y)進行繪制連線即可

但是問題出現(xiàn)了,如果我們直接一步LineTo(x绒怨,y)到終點纯赎,會出現(xiàn)以下情況:

繪制成直線了

顯然,我們不能一步就繪制起點和終點

那么問題又回到了繪制局部曲線的理論南蹂,我們將起點(dt = 0)和終點( dt = t)之間構(gòu)造出N個dt犬金,利用微分的思想繪制可以很方便的繪制出這段曲線

繪制真正的曲線

這段代碼請自行感悟

繪制曲線的流程

至此我們只要知道a對應(yīng)的dt,利用微分思想六剥,就可以繪制任意方向的局部曲線動效

6. 飛機做曲線運動晚顷,且隨著曲線方向?qū)崟r旋轉(zhuǎn)方向:

我們飛機是svg矢量圖,利用canvas的drawImage非常容易繪制出飛機仗考,但是問題是計算機是不知道飛機的機頭要跟隨其運動的方向旋繞,這是我們的所常識決定的词爬,所以我們要利用計算機仿真這個常識

單純的繪制飛機svg(不符合常識)


我們觀察很容易發(fā)現(xiàn)飛機的旋轉(zhuǎn)是沿著運動軌跡的切線方向秃嗜,其正負值由運動方向決定,如果我們知道任意時刻dt的曲線切線與水平軸的夾角d,那么利用canvas的rotate(d)就可以改變飛機的旋轉(zhuǎn)角度锅锨,并且保證其旋轉(zhuǎn)的角度和曲線相切叽赊,就可以模仿這個常識

問題就抽象出計算曲線任意時刻dt的切線與水平軸的夾角?

計算切線必搞,其實就是求導(dǎo)必指,而我們之前就已經(jīng)計算好dt對應(yīng)的兩個方向的偏導(dǎo)數(shù)方程式,這里只需要計算兩個運動方向的夾角即可恕洲,我們利用arctan vy / vx 就可以計算出該時刻切線與水平軸的夾角

計算切線角度后實時旋轉(zhuǎn)

7. 飛機在運動過程中的大小變化

這一步就非常簡單了塔橡,我們已知飛機的運動過程由t決定,而t在[0霜第,1]之間葛家,我們利用canvas的scale讓飛機運動在[0,1/2 * L]的時候從0到1放大泌类,在運動的[1/2 * L癞谒,L]的時候從1到0縮小即可

那么問題就抽象成構(gòu)造一個分段函數(shù)去計算scale的值

利用初中數(shù)學(xué)很容易構(gòu)造出該分段函數(shù)

分段函數(shù)計算縮放

至此我們就可以用[0,1]去映射[0,1]變化到[1,0],完成飛機運動的縮放

8. 剩下基本是canvas的知識運用了刃榨,比如save和restore的結(jié)合弹砚,lineTo和moveTo的結(jié)合,漸變填充createLinearGradient等枢希,都非常簡單的純api調(diào)用桌吃,這里就不題了

現(xiàn)在,需求歸納和技術(shù)原理晴玖,實現(xiàn)難點读存,數(shù)學(xué)模型都已經(jīng)推理完,接下來的才到最后一步呕屎,編程實現(xiàn)让簿,而這一步單純考驗讀者原生JS,閉包秀睛,異步編程的功底尔当,相比之前的算法分析,顯得簡單的太多了

最后我們可以從這個案例總結(jié)出幾點:

1. 一個優(yōu)秀的程序員可以抽象出整個世界

2. 優(yōu)秀的數(shù)學(xué)功底蹂安,很多本質(zhì)上的原理椭迎,都是數(shù)學(xué)原理的實際運用

3. 算法永遠是編程的靈魂,編程只是實現(xiàn)田盈,算法是先驅(qū)畜号,也是核心大腦

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市允瞧,隨后出現(xiàn)的幾起案子简软,更是在濱河造成了極大的恐慌蛮拔,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痹升,死亡現(xiàn)場離奇詭異建炫,居然都是意外死亡,警方通過查閱死者的電腦和手機疼蛾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門肛跌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人察郁,你說我怎么就攤上這事衍慎。” “怎么了绳锅?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵西饵,是天一觀的道長。 經(jīng)常有香客問我鳞芙,道長眷柔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任原朝,我火速辦了婚禮驯嘱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喳坠。我一直安慰自己鞠评,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布壕鹉。 她就那樣靜靜地躺著剃幌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪晾浴。 梳的紋絲不亂的頭發(fā)上负乡,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音脊凰,去河邊找鬼抖棘。 笑死,一個胖子當著我的面吹牛狸涌,可吹牛的內(nèi)容都是我干的切省。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼帕胆,長吁一口氣:“原來是場噩夢啊……” “哼朝捆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起懒豹,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤芙盘,失蹤者是張志新(化名)和其女友劉穎诊杆,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體何陆,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年豹储,在試婚紗的時候發(fā)現(xiàn)自己被綠了贷盲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡剥扣,死狀恐怖巩剖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钠怯,我是刑警寧澤佳魔,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站晦炊,受9級特大地震影響鞠鲜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜断国,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一贤姆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稳衬,春花似錦霞捡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至街夭,卻和暖如春砰碴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背莱坎。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工衣式, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人檐什。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓碴卧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乃正。 傳聞我的和親對象是個殘疾皇子住册,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

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