7F-畫版

連結
使用語言
HTML、CSS、Bootstrap、JavaScript(ES6)、Canvas API
BOSS 弱點
- 【特定技術】遊戲規則
- 繪圖區請使用 Canvas 來設計,上方的控制列與下方的畫筆調整可不用
- SAVE :點擊後可直接下載轉出的 PNG 圖片
- CLEAR ALL:清除畫版樣式
- UNDO、REDO:上一步、下一步
- 點擊箭頭時,功能列介面皆可進行收闔
- 【擴充功能】請再自行增加「兩個功能」,我相信勇者們都是很有梗的~
擴充功能
- 支援手機操作
- 支援手機版型
- 橡皮擦
心得
這次是我第一次使用 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;
let 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