Upload All

This commit is contained in:
Alan
2018-02-26 14:09:18 +08:00
parent 42d3a3fc46
commit 46257f08b0
1024 changed files with 204324 additions and 0 deletions

340
public/js/drawing_tools.js Normal file
View File

@ -0,0 +1,340 @@
/**
* @typedef CPosition
* @prop {number} X 平面座標上的X。
* @prop {number} Y 平面座標上的Y。
*/
/**
* 滑鼠狀態的列舉。
* @readonly
* @enum {number}
*/
const MouseStatus = Object.freeze({MouseDown: 0, Drawing: 1, MouseUp: 2, MouseMoving: 3});
/** @type {HTMLElement} */
let cvsCanvas = document.getElementById("cvsCanvas"); // 畫布(Canvas)的HTML物件
/** @type {CanvasRenderingContext2D} */
let context = cvsCanvas.getContext("2d"); // 操縱繪圖動作的相關函式集。
/** 以Id對應不同的筆刷模式。有: 筆刷、滑筆、燕筆、刺筆、印筆 */
let BrushMethods = {
"normalBrush": NormalBrush_Drawing,
"slideBrush": SlideBrush_Drawing,
"featherBrush": FeatherBrush_Drawing,
"furBrush": FurBrush_Drawing,
"stampBrush": StampBrush_Drawing
};
/* ============================ 紀錄HTML物件 ============================ */
let sizeGroupText = document.getElementById("sizeGroupText");
let strokeSizeGroupText = document.getElementById("strokeSizeGroupText");
/* ======================== 紀錄繪圖工具的相關狀態 ======================== */
let isMouseDown = false; // 紀錄滑鼠是否為壓下的狀態
let lastPosition = {X: 0, Y: 0}; // 紀錄上一次的點的座標
let curPosition = {X: 0, Y: 0}; // 紀錄目前的滑鼠座標位置
let brushWidth = 1; // 紀錄目前使用者設定的筆刷大小
let fillWidth = 1; // 紀錄目前使用者設定的填充大小
let strokeColor = "#000000"; // 紀錄目前使用者所設定的比刷顏色
let fillColor = "#000000"; // 紀錄目前使用者所設定的填滿顏色
let activedBrush = document.getElementById("normalBrush"); // 紀錄目前在使用的比刷模式的HTML物件
let DrawingMethod = NormalBrush_Drawing; // 紀錄目前的繪畫模式
/* ============================== 簽署事件 ============================== */
cvsCanvas.addEventListener("mousedown", cvsCanvas_MouseDown);
cvsCanvas.addEventListener("mousemove", cvsCanvas_MouseMove, false);
cvsCanvas.addEventListener("mouseup", cvsCanvas_MouseUp, false);
document.getElementById("resetCanvas").addEventListener("click", ClearCanvas);
document.getElementById("normalBrush").addEventListener("click", ChangeBrushMethod);
document.getElementById("slideBrush").addEventListener("click", ChangeBrushMethod);
document.getElementById("featherBrush").addEventListener("click", ChangeBrushMethod);
document.getElementById("furBrush").addEventListener("click", ChangeBrushMethod);
document.getElementById("stampBrush").addEventListener("click", ChangeBrushMethod);
document.getElementById("mainColorPicker").addEventListener("change", ChangeColor, false);
document.getElementById("subColorPicker").addEventListener("change", ChangeColor, false);
document.getElementById("subColorPicker").addEventListener("click", e => e.stopPropagation() ); //防止按下按鈕時會動到上一層的sub-color-picker
document.getElementById("sizeUp").addEventListener("click", () => ChangeFillSize(1));
document.getElementById("sizeDown").addEventListener("click", () => ChangeFillSize(-1));
document.getElementById("sizeUp10").addEventListener("click", () => ChangeFillSize(10));
document.getElementById("sizeDown10").addEventListener("click", () => ChangeFillSize(-10));
document.getElementById("strokeSizeUp").addEventListener("click", () => ChangeStrokeSize(1));
document.getElementById("strokeSizeDown").addEventListener("click", () => ChangeStrokeSize(-1));
document.getElementById("strokeSizeUp10").addEventListener("click", () => ChangeStrokeSize(10));
document.getElementById("strokeSizeDown10").addEventListener("click", () => ChangeStrokeSize(-10));
/**
* 畫布初始化。
*/
if (paintingId) {
let paintImg = document.createElement("img");
paintImg.style = "display: none;";
paintImg.onload = () => context.drawImage(paintImg, 0, 0, 800, 450);
paintImg.src = "/db/paintings/" + paintingId + ".png";
document.body.appendChild(paintImg);
}
else {
context.fillStyle = "#FFFFFF";
context.fillRect(0, 0, 800, 450);
context.fill();
}
/**
* 當「重置」按鈕按下之後,清除畫布。
* @param {Event} event 事件物件。
*/
function ClearCanvas(event) {
context.fillStyle = "#FFFFFF";
context.fillRect(0, 0, 800, 450);
context.fill();
}
/**
* 變更筆刷模式。當筆刷模式按鈕按下時所做的處理。
* @param {Event} event 事件物件。
*/
function ChangeBrushMethod(event) {
activedBrush.classList.remove("active");
activedBrush = event.target;
activedBrush.classList.add("active");
DrawingMethod = BrushMethods[activedBrush.id];
}
/**
* 變更顏色。當筆刷顏色或填充顏色按鈕按下時,並選取完顏色後的事件處理。
* @param {Event} event 事件物件。
*/
function ChangeColor(event) {
let target = event.target ? event.srcElement : event.target;
if (target.id == "mainColorPicker") {
fillColor = target.value;
}
else {
strokeColor = target.value;
}
}
/**
* 變更筆刷的粗細大小。
* @param {number} value 變更量。
*/
function ChangeStrokeSize(value) {
brushWidth += value;
if (brushWidth > 128) brushWidth = 128;
if (brushWidth < 1) brushWidth = 1;
strokeSizeGroupText.innerText = "筆刷粗細 " + brushWidth;
}
/**
* 變更填充的粗細大小。
* @param {number} value 變更量。
*/
function ChangeFillSize(value) {
fillWidth += value;
if (fillWidth > 128) fillWidth = 128;
if (fillWidth < 1) fillWidth = 1;
sizeGroupText.innerText = "填色大小 " + fillWidth;
}
/**
* 取得滑鼠在畫布中的位置。
* @param {Event} event 事件物件。限定滑鼠動作相關的事件。
* @return {Position} 目前游標的座標。
*/
function GetMousePosition(event) {
let rect = cvsCanvas.getBoundingClientRect();
return {X: event.clientX - rect.left, Y: event.clientY - rect.top};
}
/**
* 當滑鼠在畫布上按下時,所觸發的事件。
* @param {Event} event 事件物件。
*/
function cvsCanvas_MouseDown(event) {
isMouseDown = true;
DrawingMethod(event, MouseStatus.MouseDown);
}
/**
* 當滑鼠在畫布上移動時,所觸發的事件。
* @param {Event} event 事件物件。
*/
function cvsCanvas_MouseMove(event) {
DrawingMethod(event, isMouseDown ? MouseStatus.Drawing : MouseStatus.MouseMoving);
}
/**
* 當滑鼠在畫布上放開時,所觸發的事件。
* @param {Event} event 事件物件。
*/
function cvsCanvas_MouseUp(event) {
isMouseDown = false;
DrawingMethod(event, MouseStatus.MouseUp);
}
/**
* 在指定位置畫上圓。
* @param {CPosition} pos 圓心位置。
* @param {number} radius 圓的半徑。
* @param {string?} color 顏色。
*/
function FillCircle(pos, radius, color) {
if (color) context.fillStyle = color;
context.beginPath();
context.arc(pos.X, pos.Y, radius, 0, 2 * Math.PI);
context.closePath();
context.fill();
}
/**
* 在指定兩個座標之間畫線。
* @param {CPosition} posA 起點座標位置。
* @param {CPosition} posB 終點座標位置。
* @param {string?} color 顏色。
*/
function DrawLine(posA, posB, color) {
if (color) context.strokeStyle = color;
context.beginPath();
context.moveTo(posA.X, posA.Y);
context.lineTo(posB.X, posB.Y);
context.closePath();
context.stroke();
}
/**
* 在指定坐標上繪製外內圓。
* @param {CPosition} pos 圓心座標位置。
* @param {number} radius 圓的半徑。
* @param {string} strokeColor 外圓的顏色。
* @param {string} fillColor 內圓的顏色。
*/
function StampCircle(pos, radius, strokeColor, fillColor) {
if (strokeColor) context.strokeStyle = strokeColor;
if (fillColor) context.fillStyle = fillColor;
context.beginPath();
context.arc(pos.X, pos.Y, radius, 0, 6.28);
context.closePath();
context.fill();
context.stroke();
}
/**
* 筆刷模式「筆刷」下的繪圖動作。
* @param {Event} event 與滑鼠動作相關的事件物件。
* @param {MouseStatus} status 滑鼠的狀態。
*/
function NormalBrush_Drawing(event, status) {
switch(status) {
case MouseStatus.MouseDown:
lastPosition = GetMousePosition(event);
context.lineWidth = brushWidth;
context.strokeStyle = strokeColor;
FillCircle(lastPosition, brushWidth / 2, strokeColor);
break;
case MouseStatus.Drawing:
curPosition = GetMousePosition(event);
DrawLine(lastPosition, curPosition);
FillCircle(curPosition, brushWidth / 2);
lastPosition = curPosition;
}
}
/**
* 筆刷模式「滑筆」下的繪圖動作。
* @param {Event} event 與滑鼠動作相關的事件物件。
* @param {MouseStatus} status 滑鼠的狀態。
*/
function SlideBrush_Drawing(event, status) {
switch(status) {
case MouseStatus.MouseDown:
lastPosition = GetMousePosition(event);
curPosition = lastPosition;
context.lineWidth = brushWidth;
context.strokeStyle = strokeColor;
FillCircle(lastPosition, brushWidth / 2, strokeColor);
setTimeout(SlideBrush_Chasing, 10);
break;
case MouseStatus.Drawing:
curPosition = GetMousePosition(event);
}
}
/**
* 筆刷模式「滑筆」下的滑筆繪製動作。
*/
function SlideBrush_Chasing() {
let dx = (curPosition.X - lastPosition.X) / 100, dy = (curPosition.Y - lastPosition.Y) / 100;
let nextPosition = {X: lastPosition.X + dx, Y: lastPosition.Y + dy};
DrawLine(lastPosition, nextPosition);
FillCircle(nextPosition, brushWidth / 2);
lastPosition = nextPosition;
if (isMouseDown && DrawingMethod == SlideBrush_Drawing)
setTimeout(SlideBrush_Chasing, 10);
}
let featherEnable = false;
/**
* 筆刷模式「燕筆」下的繪圖動作。 (燕尾筆)
* @param {Event} event 與滑鼠動作相關的事件物件。
* @param {MouseStatus} status 滑鼠的狀態。
*/
function FeatherBrush_Drawing(event, status) {
switch(status) {
case MouseStatus.MouseDown:
lastPosition = GetMousePosition(event);
context.strokeStyle = strokeColor;
context.lineWidth = brushWidth;
FillCircle(lastPosition, brushWidth / 2, strokeColor);
featherEnable = true;
break;
case MouseStatus.Drawing:
if (!featherEnable) break;
curPosition = GetMousePosition(event);
DrawLine(lastPosition, curPosition);
FillCircle(curPosition, context.lineWidth / 2);
lastPosition = curPosition;
context.lineWidth -= 0.5;
featherEnable = context.lineWidth - 0.5 > 0;
}
}
/**
* 筆刷模式「刺筆」下的繪圖動作。
* @param {Event} event 與滑鼠動作相關的事件物件。
* @param {MouseStatus} status 滑鼠的狀態。
*/
function FurBrush_Drawing(event, status) {
switch(status) {
case MouseStatus.MouseDown:
lastPosition = GetMousePosition(event);
context.strokeStyle = strokeColor;
context.lineWidth = brushWidth;
FillCircle(lastPosition, brushWidth / 2, strokeColor);
break;
case MouseStatus.Drawing:
curPosition = GetMousePosition(event);
let dx = curPosition.X - lastPosition.X, dy = curPosition.Y - lastPosition.Y;
dx = dx > 40 ? 2 : dx / 20;
dy = dy > 40 ? 2 : dy / 20;
DrawLine(lastPosition, curPosition);
FillCircle(curPosition, brushWidth / 2);
lastPosition.X += dx;
lastPosition.Y += dy;
}
}
/**
* 筆刷模式「印筆」下的繪圖動作。
* @param {Event} event 與滑鼠動作相關的事件物件。
* @param {MouseStatus} status 滑鼠的狀態。
*/
function StampBrush_Drawing(event, status) {
switch(status) {
case MouseStatus.MouseDown:
context.strokeStyle = strokeColor;
context.fillStyle = fillColor;
context.lineWidth = brushWidth;
StampCircle(GetMousePosition(event), fillWidth / 2);
break;
case MouseStatus.Drawing:
StampCircle(GetMousePosition(event), fillWidth / 2);
}
}