Javascript is required

May 30, 2019

【JavaScript】JS地下城-7F-畫版

【JavaScript】JS地下城-7F-畫版

7F-畫版

wp-image-361

連結

Demo

Code

使用語言

HTML、CSS、Bootstrap、JavaScript(ES6)、Canvas API

BOSS 弱點

  1. 【特定技術】遊戲規則
    1. 繪圖區請使用 Canvas 來設計,上方的控制列與下方的畫筆調整可不用
    2. SAVE :點擊後可直接下載轉出的 PNG 圖片
    3. CLEAR ALL:清除畫版樣式
    4. UNDO、REDO:上一步、下一步
    5. 點擊箭頭時,功能列介面皆可進行收闔
  2. 【擴充功能】請再自行增加「兩個功能」,我相信勇者們都是很有梗的~

擴充功能

  • 支援手機操作
  • 支援手機版型
  • 橡皮擦

心得

這次是我第一次使用 Bootstrap,之前從來都沒有用過,所以一開始查了蠻多資料了,也不知道用的方法正不正確,不過官方文檔寫得很棒所以其實上手並不難。

Canvas API 的部分,最基礎的畫畫功能其實很簡單,參考 Google
到的文章,很快就可以寫出最基本的東西,之後加上去的功能…花的時間比較多。

點一下畫筆可以切換橡皮擦跟畫筆,橡皮擦是用背景顏色去做的。

之前從來沒有寫過 CSS 的動畫,所以一開始也是去翻文檔,這部分卡了比較久一點,版型我花了超久才弄好…

功能

SAVE

生成一個 Element 把該填的資料填進去,之後再用 click() 觸發。

const link = document.createElement('a')
link.href = canvas.toDataURL()
link.download = 'cancas.png'
link.click()

CLEAR ALL

clearRect() 指定範圍清空。

ctx.clearRect(0, 0, canvas.width, canvas.height)

UNDO & REDO

參考資料:連結

做法是用兩個陣列 undoDataStack[]redoDataStack[] 儲存 UNDO & REDO 的
ctx.getImageData() 資料。

還有一個選項是 STACK_MAX_SIZE 可以設定最高紀錄多少步驟,防止瀏覽器效能不足。

控制 .disable 在沒有下一步時關閉按鈕。

const STACK_MAX_SIZE = 30
const undoDataStack = []
let redoDataStack = []
const saveDraw = () => {
  redoDataStack = []
  document.querySelector('.nav-redo').classList.add('disable')
  if (undoDataStack.length >= STACK_MAX_SIZE) { undoDataStack.pop() }

  undoDataStack.unshift(ctx.getImageData(0, 0, canvas.width, canvas.height))
  document.querySelector('.nav-undo').classList.remove('disable')
}
const undo = () => {
  if (undoDataStack.length <= 0) return
  redoDataStack.unshift(ctx.getImageData(0, 0, canvas.width, canvas.height))
  document.querySelector('.nav-redo').classList.remove('disable')
  const imageData = undoDataStack.shift()
  ctx.putImageData(imageData, 0, 0)
  if (undoDataStack.length <= 0) { document.querySelector('.nav-undo').classList.add('disable') }

}
const redo = () => {
  if (redoDataStack.length <= 0) return
  undoDataStack.unshift(ctx.getImageData(0, 0, canvas.width, canvas.height))
  document.querySelector('.nav-undo').classList.remove('disable')
  const imageData = redoDataStack.shift()
  ctx.putImageData(imageData, 0, 0)
  if (redoDataStack.length <= 0) { document.querySelector('.nav-redo').classList.add('disable') }

}

手機版操作

觸控螢幕監聽事件

canvas.addEventListener('touchstart', touchStart) // mousedown
canvas.addEventListener('touchmove', touchMove) // mousemove
canvas.addEventListener('touchend', touchEnd) // mouseup

參考資料

Canvas APIの基礎

Bootstrap - Document

HTML5 Canvas 簡易手繪板

Canvas 教學文件- Web APIs | MDN

canvasを画像としてダウンロードさせたかった話

Canvasで元に戻す(Undo),やり直し(Redo)を実装する方法

Webデザインの知識がなくてもOK!Bootstrapの使い方【入門者向け】

Tags