[Hero Of UnderGround 地下城] — 7F Canvas 畫板
成果 & 程式碼
Introduction & 前言
自從接觸 JS 後一直不敢觸碰的一塊,還記得前陣子碰到朋友在做抽抽樂轉盤,那時候便是看她用 Canvas 做出來的,狹路相逢(誤),出來混總是要還的,這次的大魔王就是 Canvas 了!
Summary & 摘要
由於JS地下城每個BOSS的弱點都不一樣,每一層都要由弱點去進行攻略,本次BOSS的弱點有二 項。
- 【特定技術】遊戲規則
繪圖區請使用 Canvas 來設計,上方的控制列與下方的畫筆調整可不用
-> a.SAVE :點擊後可直接下載轉出的 PNG 圖片
-> b.CLEAR ALL:清除畫版樣式
-> c.UNDO、REDO:上一步、下一步
-> d.點擊箭頭時,功能列介面皆可進行收闔
- 【擴充功能】請再自行增加「兩個功能」,我相信勇者們都是很有梗的~
額外條件
你攻略此 BOSS 的攻略過程心得
你學習 Canvas 的學習過程
為什麼要用 Canvas,與一般 DOM 繪製有什麼優缺點?
萬事起頭難…..嗎?
起頭難不難,其實要先感謝 Huiyu 大大,因為很多東西都算是菜雞我第一次接觸,所以會先去爬文看看其他大佬們如何起手。這邊參考了一位國外大神的 Youtube ,教你如何創造出簡單的畫布。
這次切版也用到比較多的動畫,順便訓練一下流暢性,還有順便解決 BOSS 的第一個弱點知一 d 。但搞切版就花了半天去了,原諒我菜TAT,比較特別的部分就是前面多位大大提過的 input color 了,後面的部分會提到。
讚嘆感嘆便利的網路還有多位大神無私奉獻,現在很多東西其實不難了。
1 | <canvas *id*="drawing_board" *width*='800' *height*='800'></canvas> |
Canvas 可以說是一張畫布,而你想要在上面幹啥都行,別想歪。
預設的畫布大小是 300px * 150px(寬 * 高)。但你也可以透過 HTML 寬、高屬性(attribute)自訂。*點我前往文章*
1 | const canvas = document.getElementById('drawing_board'); |
這可以說是只要寫到 Canvas 就一定會寫到的,給他的一個變數名稱,然後指定你是要用 2d 還是 3d 來作畫,這邊我們用到 2d 就夠了。之後給他寬高,還有畫筆,畫筆顏色…等等
1 | canvas.width = window.innerWidth; |
設定完成後我們還需要做到幾件事情,既然我們要做畫板,就必須讓筆掌握在使用者手中,所以我們必須判斷使用者何時下手何時停手畫畫,然後給使用者 一個移動的監聽事件 , 一個按下滑鼠的監聽事件 , 一個放開滑鼠的監聽事件 , 最後一個滑鼠離開的監聽事件。
1 | // 判斷是不是點下滑鼠了 |
畫下第一筆
完成了鼠標的座標抓取後,我們就可以來判斷何時該畫畫了。
1 | // 滑鼠按下後 |
使用 toDataURL() 達到 UNDO REDO
1 | let step = -1; |
首先我們必須設定兩個變數,一個用來計算步數,一個用來裝轉成 Base64 編碼的圖片字串,用陣列來放,讓我們靠 Step 就能達到上一步,下一步的功能,每畫一筆,我們就跑一次 Push 的 function 讓 Step++,並把圖片的字串放進陣列裡,讓讀取的時候能取出並蓋上畫布 ,反之上一步就是 −−。
1 | function push() { |
這邊需要特別提到,因為一開始布數從 -1開始,為的是讓他可以符合陣列的特定,從 0開始算,這樣讀取時才能讀到資料,但是我們的上一步條件必須 Step > 0,所以一開始我們就必須讓 Step+1 ,不然會變成我一樣,苦惱好幾小時,為什麼第一筆畫都不能 UNDO …… 這邊感謝 7F 前端之碑主 陳顯然 大大的解答。
1 | // 上一步的function |
上一步的做法跟下一步的做法相反而已,另外剛開始寫完這段的時候怎麼試都無法上一步,一直到最後加了 ctx.clearRect 後才有了反應,這邊不知道是不是有大大說的 Canvas 不吃 CSS 的問題,會再進一步探討並研究的。
1 | <a class="save" href="#" download="我的偉大創作"> |
1 | // 儲存畫布的function |
另外儲存的部分在 html 上使用 href 去裝我們的字串,download 則是下載後的檔案名稱。
關於擴充功能
由於對 Canvas 是第一次接觸,所以就把各位大大做的功能拿來練手,畢竟菜雞腳程慢,到 7F 時各位大佬都已經飛天啦…這邊我選的功能是 橡皮擦、上傳圖片、顏色選擇器…
先說說簡單的 橡皮擦 其實就是把畫筆顏色改成背景顏色,然後看起來就像是擦掉了。
Input Color 对象是 HTML5 新增的,Input Color 對象代表了使用 type=”color”属性的 HTML 元素 。
1 | <input type="color" id="myColor"> |
隨後是我覺得超酷的功能,顏色選擇器,其實也很簡單,只是修改它的外觀比較麻煩。在 html 上加上這個之後,你會看見一個長方形的 input 但是點下去你就能選顏色了,透過 change 事件 input.value() 你就能取得使用者選擇的顏色了。然後就讓你的 ctx.strokeStyle 畫筆顏色 = input.value() 吧!
這邊非常感謝 汶穎大大 。
其中比較麻煩的應該就是上傳功能了,不過簡單理解下,就是透過 html 的 input files 上傳後,一樣透過 toDataURL() 把它轉成字串,然後用 Canvas 的 drawImage 把它畫出來。
1 | <input type="file" class="form-control-file photo-up rounded" style="display: none;" id="photo_up" /> |
需要注意的就是必須使用 Change 事件,不然圖片還沒選到,就會跑進裡面讀你的陣列有沒有圖片,會造成錯誤。
Canvas 的學習過程
這次可以說是踩雷踩了又踩,看別人寫的 Code 像是數學老師解題一樣,自己寫出來又是一回事,不過就正式這樣才有成長,從剛開始什麼都不懂,現在至少能畫個圓形和直線出來…噗
為什麼要用 Canvas?
Canvas 除了能做到畫畫 還能做出非常具有特色的3D遊戲,及動畫,重點是方便且快速,所以非常多人使用,必且在大神的學習在釋出的寶貴經驗之中, Canvas 甚至被做成了非常方便的套件。
03/19更新 — 熟用 fillStyle 及 fillRect 別讓背景離家出走
由於沒注意到下載後背景的顏色,造成一開始背景是透明的,讓我大驚失色。詳細顏色設定請點我
1 | function firstpush() { |
還記得一開始說我們的** Step** 預設是 -1 對吧,一開始我們進來必須設定一個 function 去讓它加一,我們就可以在裡面加上背景顏色,fillStyle 其實就是設定要填滿的顏色,記得要配上 **fillRect **服用,它是 用於填充繪圖的顏色、漸變或模式,預設是黑色,你也可以設定一定的大小範圍去填滿它,例如 **ctx.fillRect(20,20,150,100)**。
gradient 讓你的人生有起有落
配上 gradient 或 pattern 服用,可以創造出漸層,也可以使用後者讓你的圖片填充你的畫布。
取自W3School 點我看文章
1 | // 起手式 |
ctx.createLinearGradient(漸變開始點的 x 座標,
漸變開始點的 y 座標,漸變結束點的 x 座標,漸變結束的 y 座標)
詳細說明請點我查看
Conclusion & 結論
我想這次的 7F 不算破關,是靠著眾多前人智慧以及萬能谷歌大神,讓我學到了寶貴的一課,關於 Canvas 還有很多值得我去探討,這是較不容易學會卻是非常好用的東西之一,身為一位勇者,就是必須一直嘗試跌倒在嘗試啊。
雖然每一層樓都有主要的目標 BOSS 在,但卻會常常在路上學到其他壯大自己的知識,比如這次意外學習到 ES6 的 模板源文本(template strings ,有興趣可以點我查看,最後除了繼續努力之外還是要列出檢討的地方,然後朝下一關繼續加油,完畢。(這次真的需要好好加油呀…
JS
邏輯
文筆
體重
我的其他範例
Hero Of UnderGround — 1F Multiplicatio 九九乘法表
Hero Of UnderGround — 2F Clock 時鐘
Hero Of UnderGround — 3F Calculator 計算機
Hero Of UnderGround — 4F World Clock 各國時區
Hero Of UnderGround — 5F AQI 全台空氣指標儀表板
Hero Of UnderGround — 6F SECONDS CHALLENGE 倒數遊戲
參考網站
- 陳顯然大大的 — Canvas畫版
- HuiyuLiz大大的 — GitHub
- Dosmanthus大大 — ES6 — Template Strings
- W3school 教學網站
- Runoob — input color
- MDN — Canvas
- 汶穎大大 — 圖片上傳
- 巴哈姆特 舒壓用