使用 canvas 實(shí)現(xiàn)玩具瀏覽器的學(xué)習(xí)思考

在極客時(shí)間的《重學(xué)前端》的瀏覽器工作原理唐础,最后 winter 提到了可以試著用 canvas 來(lái)實(shí)現(xiàn)一個(gè)玩具瀏覽器揽思。所以了解下 canvas玩荠。

其實(shí)關(guān)于 canvas 的教學(xué)文章很多辛块,特別是 MDN 中的 canvas 教程非常好存捺。所以我這里寫個(gè)基礎(chǔ)教程意義也不大槐沼。簡(jiǎn)單說下我理解的 canvas。

我理解的 canvas

canvas 說簡(jiǎn)單也簡(jiǎn)單捌治,說復(fù)雜則非常復(fù)雜岗钩。
簡(jiǎn)單是因?yàn)?canvas 的基礎(chǔ)知識(shí)就是基于 <canvas> 標(biāo)簽元素的 context 上下文來(lái)繪制圖形,具體有哪些繪制方法很多教程和書上都有介紹肖油。
復(fù)雜則是因?yàn)?canvas 可以實(shí)現(xiàn)非常復(fù)雜的功能兼吓。如復(fù)雜圖像繪制、圖像效果處理森枪、圖像特效提價(jià)视搏、動(dòng)畫,甚游戲等县袱,具體可以看下《HTML5 Canvas核心技術(shù)》一書了解 canvas 的強(qiáng)大之處浑娜。

對(duì)于我而言只是想實(shí)現(xiàn)簡(jiǎn)單的 2d 頁(yè)面效果,所以就簡(jiǎn)單學(xué)習(xí)了一下 canvas 繪制功能式散。大概有以下幾點(diǎn):

  • canvas 基本用法
const canvas = document.getElementById('page');
const ctx = canvas.getContext('2d');
  • 繪制圖形:矩形筋遭、弧形、路徑暴拄、文本漓滔、圖片
  • 圖形樣式設(shè)置:顏色、邊框乖篷、寬高响驴、位置
  • 圖形事件:鼠標(biāo)事件、鍵盤事件

其實(shí)之前用 canvas 實(shí)現(xiàn)過折線圖表單來(lái)呈現(xiàn)數(shù)據(jù)撕蔼,使用的是 zrender 庫(kù)踏施。具體文章可以看下我之前寫的使用ZRender實(shí)現(xiàn)護(hù)理單折線圖功能一文石蔗。

關(guān)于玩具瀏覽器的實(shí)現(xiàn)思路

之前的文章中聊到過瀏覽器的工作原理,那么如何使用 canvas 實(shí)現(xiàn)一個(gè)玩具瀏覽器畅形,我的思路是這樣的:

結(jié)構(gòu):

  1. 瀏覽器由一個(gè)文本框和一個(gè) canvas 構(gòu)成养距。
<input />
<canvas id="browser" width="600" height="500"></canvas>

獲取資源行為:

  1. 在文本框中輸入 URL,點(diǎn)擊回車鍵執(zhí)行訪問 URL 行為日熬。
  2. 通過 ajax 獲取到數(shù)據(jù)棍厌,響應(yīng)內(nèi)容應(yīng)該是一段 HTML 代碼。
  3. 解析 HTML 代碼竖席,如果遇到外部 URL 資源需要另行獲取耘纱。

解析代碼行為:

  1. 將 HTML 代碼解析成一個(gè) DOM 樹對(duì)象。
  2. 解析 CSS 的代碼并根據(jù) DOM 樹對(duì)象創(chuàng)建 CSSOM 樹對(duì)象毕荐,將 DOM 元素和 CSSOM 一一對(duì)應(yīng)束析。

渲染行為:

  1. 將 CSSOM 對(duì)象中的 CSS 規(guī)則寫到 DOM 樹對(duì)象中,構(gòu)成 Render 樹對(duì)象憎亚。
  2. 自上而下遍歷 Render 樹對(duì)象员寇,根據(jù)元素的樣式計(jì)算元素的寬高和位置存儲(chǔ)在 Render 。
  3. 知道了元素的內(nèi)容第美、寬高蝶锋、位置后,就可以遍歷 Render 樹對(duì)象用 canvas API 來(lái)繪制整個(gè)頁(yè)面了什往。
  4. 使用 canvas 的事件來(lái)替代 DOM 元素的事件扳缕。

重排和重繪行為:

  1. 如果元素尺寸的變化梯刚,需要重新計(jì)算整個(gè)頁(yè)面元素位置排版逗威,清空畫布重新繪制整個(gè)頁(yè)面挽放。
  2. 如果是元素背景顏色的變化纤虽,直接使用 canvas 重新繪制元素。

難點(diǎn)

  • 解析 HTML 和 CSS 為 DOM 樹對(duì)象和 CSSOM 樹對(duì)象硅瞧。
  • 流式計(jì)算元素位置冠跷。
  • 遍歷 Render 樹對(duì)象中的元素信息和樣式信息計(jì)算排版信息合是。

最后

其實(shí)在 Vue.js 的 Visual DOM 中有 parseHTML 相關(guān)的代碼衫樊,原理上也差不多。的確可以試著去實(shí)現(xiàn)以下 canvas 版的瀏覽器利花。

以上只是我暫時(shí)的想法科侈,要真正實(shí)現(xiàn)其實(shí)還有很多問題。比如:

  • input炒事、textarea 怎么實(shí)現(xiàn)
  • 那么多 CSS 屬性如何涵蓋
  • 瀏覽器的 HTML 容錯(cuò)機(jī)制如何實(shí)現(xiàn)
  • 瀏覽器頁(yè)面滾動(dòng)如何實(shí)現(xiàn)
  • 如何處理 HTML 中的外部 URL 資源
  • 頁(yè)面中的復(fù)雜組件怎么實(shí)現(xiàn)

所以臀栈,其實(shí)一個(gè)瀏覽器可以做的東西非常多。正如 winter 所說:

一旦你做到了挠乳,收益會(huì)非常大权薯。

如果對(duì)開發(fā) canvas 的瀏覽器有興趣姑躲,也可以想想怎么來(lái)實(shí)現(xiàn)。也歡迎留言討論盟蚣。

參考資料

  • 重學(xué)前端 | 極客時(shí)間
  • 《JavaScript 高級(jí)程序設(shè)計(jì)》
  • 《JavaScript 權(quán)威指南》
  • 《HTML5 Canvas核心技術(shù)》
  • Canvas教程 - Web API 接口參考 | MDN
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末黍析,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屎开,更是在濱河造成了極大的恐慌阐枣,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奄抽,死亡現(xiàn)場(chǎng)離奇詭異蔼两,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)逞度,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門额划,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人档泽,你說我怎么就攤上這事俊戳。” “怎么了茁瘦?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵品抽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我甜熔,道長(zhǎng)圆恤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任腔稀,我火速辦了婚禮盆昙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘焊虏。我一直安慰自己淡喜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布诵闭。 她就那樣靜靜地躺著炼团,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疏尿。 梳的紋絲不亂的頭發(fā)上瘟芝,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音褥琐,去河邊找鬼锌俱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敌呈,可吹牛的內(nèi)容都是我干的贸宏。 我是一名探鬼主播造寝,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吭练!你這毒婦竟也來(lái)了诫龙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤线脚,失蹤者是張志新(化名)和其女友劉穎赐稽,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浑侥,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姊舵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了寓落。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片括丁。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖伶选,靈堂內(nèi)的尸體忽然破棺而出史飞,到底是詐尸還是另有隱情,我是刑警寧澤仰税,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布构资,位于F島的核電站,受9級(jí)特大地震影響陨簇,放射性物質(zhì)發(fā)生泄漏吐绵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一河绽、第九天 我趴在偏房一處隱蔽的房頂上張望己单。 院中可真熱鬧,春花似錦耙饰、人聲如沸纹笼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)廷痘。三九已至,卻和暖如春件已,著一層夾襖步出監(jiān)牢的瞬間笋额,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工拨齐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鳞陨,地道東北人昨寞。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓瞻惋,卻偏偏與公主長(zhǎng)得像厦滤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子歼狼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

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