diff --git a/dist/main.js b/dist/main.js index 29a429c..e23fce7 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1,2 +1,2 @@ -!function(){"use strict";var t,s,e,a,n;t=class{constructor(t){this.canvasHandler=t,this.setupBrushSize()}setupBrushSize(){this.brushSizeInput=document.getElementById("size-slider"),this.brushSizeInput.addEventListener("input",(()=>this.updateBrushSize())),this.currentBrushSize=5}setBrushStyling(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.canvasHandler.colorHandler.currentColor,s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.currentBrushSize;this.canvasHandler.ctx.lineCap="round",this.canvasHandler.ctx.lineWidth=s,this.canvasHandler.ctx.strokeStyle=t}updateBrushSize(){this.currentBrushSize=parseInt(this.brushSizeInput.value),this.setBrushStyling()}},s=class{constructor(t){this.setupColorHandling(),this.canvasHandler=t}setupColorHandling(){this.currentColor="black",this.brushColorPicker=document.getElementById("color-picker"),this.brushColorPicker.addEventListener("input",(()=>{this.currentColor=this.brushColorPicker.value})),this.bgColorPicker=document.getElementById("background-color-picker"),this.bgColorPicker.addEventListener("input",(()=>{const t=this.canvasHandler.drawnPaths,s=this.canvasHandler.redoStack;this.canvasHandler.clear(),this.canvasHandler.drawnPaths=t,this.canvasHandler.redoStack=s,t.forEach((t=>this.canvasHandler.redrawPath(t))),this.canvasHandler.canvas.style.backgroundColor=this.bgColorPicker.value}))}},e=class{constructor(t,s,e){this.canvasHandler=t,this.canvas=this.canvasHandler.canvas,this.colorHandler=s,this.brushHandler=e,this.setupDrawingEventListeners()}setupDrawingEventListeners(){this.canvas.addEventListener("mousedown",(t=>this.startDrawing(t))),this.canvas.addEventListener("mousemove",(t=>this.draw(t))),this.canvas.addEventListener("mouseup",(()=>this.stopDrawing())),this.canvas.addEventListener("mouseout",(()=>this.stopDrawing()))}startDrawing(t){this.isDrawing||(this.currentPath=[],this.redoStack=[],this.isDrawing=!0);const s=t.clientX-this.canvas.offsetLeft,e=t.clientY-this.canvas.offsetTop;this.canvasHandler.ctx.beginPath(),this.canvasHandler.ctx.moveTo(s,e),this.currentPath.push({x:s,y:e,color:this.colorHandler.currentColor,brushSize:this.brushHandler.currentBrushSize}),this.draw(t)}draw(t){if(!this.isDrawing)return;const s=t.clientX-this.canvas.offsetLeft,e=t.clientY-this.canvas.offsetTop;this.canvasHandler.ctx.lineTo(s,e);const a=this.canvasHandler.eraserCheckbox.checked?this.colorHandler.bgColorPicker.value:this.colorHandler.currentColor;this.brushHandler.setBrushStyling(a,this.brushHandler.currentBrushSize),this.canvasHandler.ctx.stroke(),this.currentPath.push({x:s,y:e,color:a,brushSize:this.brushHandler.currentBrushSize})}stopDrawing(){this.canvasHandler.eraserCheckbox.checked&&(this.currentPath.isErase=!0),this.isDrawing&&(this.canvasHandler.drawnPaths.push(this.currentPath),this.isDrawing=!1)}},a=class{constructor(){this.setupCanvas(),this.setupCanvasProportions(),this.setupEraser(),this.setupUndoBtn(),this.setupRedoBtn(),this.setupClearBtn(),this.setupDownloadBtn(),this.colorHandler=new s(this),this.brushHandler=new t(this,this.colorHandler),this.drawingHandler=new e(this,this.colorHandler,this.brushHandler)}setupCanvas(){this.canvas=document.getElementById("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDrawing=!1}setupCanvasProportions(){this.canvas.style.position="absolute",this.canvas.style.top="100px",this.canvas.height=window.innerHeight-100-100,this.canvas.width=window.innerWidth}setupClearBtn(){this.clearBtn=document.getElementById("clear"),this.clearBtn.addEventListener("click",(()=>this.clear()))}setupEraser(){this.eraserCheckbox=document.getElementById("eraser")}setupUndoBtn(){this.drawnPaths=[],this.undoBtn=document.getElementById("undo"),this.undoBtn.addEventListener("click",(()=>this.undo()))}setupRedoBtn(){this.redoStack=[],this.redoBtn=document.getElementById("redo"),this.redoBtn.addEventListener("click",(()=>this.redo()))}setupDownloadBtn(){this.downloadBtn=document.getElementById("download"),this.downloadBtn.addEventListener("click",(()=>this.download()))}clear(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.canvas.style.backgroundColor="white",this.redoStack=[],this.drawnPaths=[]}undo(){if(this.drawnPaths.length>0){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);const t=this.drawnPaths.pop();this.drawingHandler.redoStack.push(t),this.drawnPaths.forEach((t=>this.redrawPath(t)))}}redrawPath(t){t.forEach(((s,e)=>{0===e?(this.ctx.beginPath(),this.ctx.moveTo(s.x,s.y)):(this.ctx.lineTo(s.x,s.y),t.isErase&&(s.color=this.colorHandler.bgColorPicker.value),this.brushHandler.setBrushStyling(s.color,s.brushSize),this.ctx.stroke())}))}redo(){if(this.drawingHandler.redoStack.length>0){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);const t=this.drawingHandler.redoStack.pop();this.drawnPaths.push(t),this.drawnPaths.forEach((t=>this.redrawPath(t)))}}download(){const t=document.createElement("canvas"),s=t.getContext("2d");t.width=this.canvas.width,t.height=this.canvas.height,s.fillStyle=this.canvas.style.backgroundColor,s.fillRect(0,0,t.width,t.height),s.drawImage(this.canvas,0,0);const e=t.toDataURL("image/png"),a=document.createElement("a");a.href=e,a.download="canvas.png",a.click()}},n=class{constructor(){this.brushRadio=document.getElementById("brush"),this.eraserRadio=document.getElementById("eraser"),this.brushLabel=document.querySelector('label[for="brush"]'),this.eraserLabel=document.querySelector('label[for="eraser"]'),this.detectChange(),this.updateIcon()}updateIcon(){this.brushLabel.querySelector("img").src=this.brushRadio.checked?"assets/tab-icon.png":"assets/menu icons/not-active-brush.png",this.eraserLabel.querySelector("img").src=this.eraserRadio.checked?"assets/menu icons/active-eraser.png":"assets/menu icons/not-active-eraser.png"}detectChange(){[this.brushRadio,this.eraserRadio].forEach((t=>{t.addEventListener("change",(()=>this.updateIcon()))}))}},document.addEventListener("DOMContentLoaded",(()=>{new a,new n}))}(); +!function(){"use strict";var t,e,s,a,n;t=class{constructor(t){this.canvasHandler=t,this.setupBrushSize()}setupBrushSize(){this.brushSizeInput=document.getElementById("size-slider"),this.brushSizeInput.addEventListener("input",(()=>this.updateBrushSize())),this.currentBrushSize=5}setBrushStyling(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.canvasHandler.colorHandler.currentColor,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.currentBrushSize;this.canvasHandler.ctx.lineCap="round",this.canvasHandler.ctx.lineWidth=e,this.canvasHandler.ctx.strokeStyle=t}updateBrushSize(){this.currentBrushSize=parseInt(this.brushSizeInput.value),this.setBrushStyling()}},e=class{constructor(t){this.setupColorHandling(),this.canvasHandler=t}setupColorHandling(){this.currentColor="black",this.brushColorPicker=document.getElementById("color-picker"),this.brushColorPicker.addEventListener("input",(()=>{this.currentColor=this.brushColorPicker.value})),this.bgColorPicker=document.getElementById("background-color-picker"),this.bgColorPicker.addEventListener("input",(()=>{const t=this.canvasHandler.drawnPaths,e=this.canvasHandler.redoStack;this.canvasHandler.clear(),this.canvasHandler.drawnPaths=t,this.canvasHandler.redoStack=e,t.forEach((t=>this.canvasHandler.redrawPath(t))),this.canvasHandler.canvas.style.backgroundColor=this.bgColorPicker.value}))}},s=class{constructor(t,e){this.canvasHandler=t,this.colorHandler=e,this.setupDrawingEventListeners()}setupDrawingEventListeners(){this.canvasHandler.canvas.addEventListener("mousedown",(t=>this.startDrawing(t))),this.canvasHandler.canvas.addEventListener("mousemove",(t=>this.draw(t))),this.canvasHandler.canvas.addEventListener("mouseup",(()=>this.stopDrawing())),this.canvasHandler.canvas.addEventListener("mouseout",(()=>this.stopDrawing()))}startDrawing(t){this.isDrawing||(this.currentPath=[],this.redoStack=[],this.isDrawing=!0);const e=t.clientX-this.canvasHandler.canvas.offsetLeft,s=t.clientY-this.canvasHandler.canvas.offsetTop;this.canvasHandler.ctx.beginPath(),this.canvasHandler.ctx.moveTo(e,s),this.currentPath.push({x:e,y:s,color:this.colorHandler.currentColor,brushSize:this.canvasHandler.brushHandler.currentBrushSize}),this.draw(t)}draw(t){if(!this.isDrawing)return;const e=t.clientX-this.canvasHandler.canvas.offsetLeft,s=t.clientY-this.canvasHandler.canvas.offsetTop;this.canvasHandler.ctx.lineTo(e,s);const a=this.canvasHandler.eraserCheckbox.checked?this.colorHandler.bgColorPicker.value:this.colorHandler.currentColor;this.canvasHandler.brushHandler.setBrushStyling(a,this.canvasHandler.brushHandler.currentBrushSize),this.canvasHandler.ctx.stroke(),this.currentPath.push({x:e,y:s,color:a,brushSize:this.canvasHandler.brushHandler.currentBrushSize})}stopDrawing(){this.canvasHandler.eraserCheckbox.checked&&(this.currentPath.isErase=!0),this.isDrawing&&(this.canvasHandler.drawnPaths.push(this.currentPath),this.isDrawing=!1)}},a=class{constructor(){this.setupCanvas(),this.setupCanvasProportions(),this.setupEraser(),this.setupUndoBtn(),this.setupRedoBtn(),this.setupClearBtn(),this.setupDownloadBtn(),this.colorHandler=new e(this),this.brushHandler=new t(this),this.drawingHandler=new s(this,this.colorHandler)}setupCanvas(){this.canvas=document.getElementById("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDrawing=!1}setupCanvasProportions(){this.canvas.style.position="absolute",this.canvas.style.top="100px",this.canvas.height=window.innerHeight-100-100,this.canvas.width=window.innerWidth}setupClearBtn(){this.clearBtn=document.getElementById("clear"),this.clearBtn.addEventListener("click",(()=>this.clear()))}setupEraser(){this.eraserCheckbox=document.getElementById("eraser")}setupUndoBtn(){this.drawnPaths=[],this.undoBtn=document.getElementById("undo"),this.undoBtn.addEventListener("click",(()=>this.undo()))}setupRedoBtn(){this.redoStack=[],this.redoBtn=document.getElementById("redo"),this.redoBtn.addEventListener("click",(()=>this.redo()))}setupDownloadBtn(){this.downloadBtn=document.getElementById("download"),this.downloadBtn.addEventListener("click",(()=>this.download()))}clear(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.canvas.style.backgroundColor="white",this.redoStack=[],this.drawnPaths=[]}undo(){if(this.drawnPaths.length>0){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);const t=this.drawnPaths.pop();this.drawingHandler.redoStack.push(t),this.drawnPaths.forEach((t=>this.redrawPath(t)))}}redrawPath(t){t.forEach(((e,s)=>{0===s?(this.ctx.beginPath(),this.ctx.moveTo(e.x,e.y)):(this.ctx.lineTo(e.x,e.y),t.isErase&&(e.color=this.colorHandler.bgColorPicker.value),this.brushHandler.setBrushStyling(e.color,e.brushSize),this.ctx.stroke())}))}redo(){if(this.drawingHandler.redoStack.length>0){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);const t=this.drawingHandler.redoStack.pop();this.drawnPaths.push(t),this.drawnPaths.forEach((t=>this.redrawPath(t)))}}download(){const t=document.createElement("canvas"),e=t.getContext("2d");t.width=this.canvas.width,t.height=this.canvas.height,e.fillStyle=this.canvas.style.backgroundColor,e.fillRect(0,0,t.width,t.height),e.drawImage(this.canvas,0,0);const s=t.toDataURL("image/png"),a=document.createElement("a");a.href=s,a.download="canvas.png",a.click()}},n=class{constructor(){this.brushRadio=document.getElementById("brush"),this.eraserRadio=document.getElementById("eraser"),this.brushLabel=document.querySelector('label[for="brush"]'),this.eraserLabel=document.querySelector('label[for="eraser"]'),this.detectChange(),this.updateIcon()}updateIcon(){this.brushLabel.querySelector("img").src=this.brushRadio.checked?"assets/tab-icon.png":"assets/menu icons/not-active-brush.png",this.eraserLabel.querySelector("img").src=this.eraserRadio.checked?"assets/menu icons/active-eraser.png":"assets/menu icons/not-active-eraser.png"}detectChange(){[this.brushRadio,this.eraserRadio].forEach((t=>{t.addEventListener("change",(()=>this.updateIcon()))}))}},document.addEventListener("DOMContentLoaded",(()=>{new a,new n}))}(); //# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/dist/main.js.map b/dist/main.js.map index c77fdbe..6ca96f6 100644 --- a/dist/main.js.map +++ b/dist/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","mappings":"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","sources":["webpack://canvas-project/./src/scripts/brushHandler.js","webpack://canvas-project/./src/scripts/colorHandler.js","webpack://canvas-project/./src/scripts/drawingHandler.js","webpack://canvas-project/./src/scripts/canvasHandler.js","webpack://canvas-project/./src/scripts/toolIcon.js","webpack://canvas-project/./src/index.js"],"sourcesContent":["class BrushHandler {\n constructor(canvasHandler) {\n this.canvasHandler = canvasHandler;\n this.setupBrushSize();\n }\n\n setupBrushSize() {\n this.brushSizeInput = document.getElementById(\"size-slider\");\n this.brushSizeInput.addEventListener(\"input\", () => this.updateBrushSize());\n this.currentBrushSize = 5;\n }\n\n setBrushStyling(\n color = this.canvasHandler.colorHandler.currentColor,\n brushSize = this.currentBrushSize\n ) {\n this.canvasHandler.ctx.lineCap = \"round\";\n this.canvasHandler.ctx.lineWidth = brushSize;\n this.canvasHandler.ctx.strokeStyle = color;\n }\n\n updateBrushSize() {\n this.currentBrushSize = parseInt(this.brushSizeInput.value);\n this.setBrushStyling();\n }\n // dotted brush, glitter brush?\n}\n\nexport default BrushHandler;\n","class ColorHandler {\n constructor(canvasHandler) {\n this.setupColorHandling()\n this.canvasHandler = canvasHandler\n }\n\n setupColorHandling() {\n this.currentColor = \"black\";\n\n // if a brush color has been selected..\n this.brushColorPicker = document.getElementById(\"color-picker\");\n\n this.brushColorPicker.addEventListener(\"input\", () => {\n this.currentColor = this.brushColorPicker.value;\n });\n\n // if a bg color has been selected..\n this.bgColorPicker = document.getElementById(\"background-color-picker\");\n this.bgColorPicker.addEventListener(\n \"input\",\n () => {\n const drawnPaths = this.canvasHandler.drawnPaths\n const redoStack = this.canvasHandler.redoStack\n this.canvasHandler.clear()\n this.canvasHandler.drawnPaths = drawnPaths\n this.canvasHandler.redoStack = redoStack\n drawnPaths.forEach((path) => this.canvasHandler.redrawPath(path));\n this.canvasHandler.canvas.style.backgroundColor = this.bgColorPicker.value;\n }\n );\n }\n}\n\nexport default ColorHandler","class DrawingHandler {\n constructor(canvasHandler, colorHandler, brushHandler) {\n this.canvasHandler = canvasHandler;\n this.canvas = this.canvasHandler.canvas;\n this.colorHandler = colorHandler;\n this.brushHandler = brushHandler;\n this.setupDrawingEventListeners();\n }\n\n setupDrawingEventListeners() {\n this.canvas.addEventListener(\"mousedown\", (e) => this.startDrawing(e));\n this.canvas.addEventListener(\"mousemove\", (e) => this.draw(e));\n this.canvas.addEventListener(\"mouseup\", () => this.stopDrawing());\n this.canvas.addEventListener(\"mouseout\", () => this.stopDrawing());\n }\n\n // // drawing actions\n startDrawing(e) {\n if (!this.isDrawing) {\n // clear the stacks when a new drawing begins\n this.currentPath = [];\n this.redoStack = [];\n this.isDrawing = true;\n }\n\n // calculate the adjusted mouse coordinates relative to the canvas\n const canvasMouseX = e.clientX - this.canvas.offsetLeft;\n const canvasMouseY = e.clientY - this.canvas.offsetTop;\n\n // begin a new path in the canvas ctx & move to initial drawing pos\n this.canvasHandler.ctx.beginPath();\n\n // move the brush to the adjusted mouse coordinates\n this.canvasHandler.ctx.moveTo(canvasMouseX, canvasMouseY);\n\n // store the starting point in the drawing path\n this.currentPath.push({\n x: canvasMouseX,\n y: canvasMouseY,\n color: this.colorHandler.currentColor,\n brushSize: this.brushHandler.currentBrushSize,\n });\n\n // draw a dot at the starting point\n this.draw(e);\n }\n\n draw(e) {\n if (!this.isDrawing) return;\n\n // calculate the adjusted mouse coordinates relative to the canvas\n const mouseX = e.clientX - this.canvas.offsetLeft;\n const mouseY = e.clientY - this.canvas.offsetTop;\n\n // connect the current drawing position to the new position\n this.canvasHandler.ctx.lineTo(mouseX, mouseY);\n\n // Set brush styling based on whether eraser or brush is checked\n const color = this.canvasHandler.eraserCheckbox.checked\n ? this.colorHandler.bgColorPicker.value\n : this.colorHandler.currentColor;\n\n this.brushHandler.setBrushStyling(\n color,\n this.brushHandler.currentBrushSize\n );\n\n // draw the line on the canvas\n this.canvasHandler.ctx.stroke();\n\n // store the current point in the drawing path\n this.currentPath.push({\n x: mouseX,\n y: mouseY,\n color: color,\n brushSize: this.brushHandler.currentBrushSize,\n });\n }\n\n stopDrawing() {\n if (this.canvasHandler.eraserCheckbox.checked)\n this.currentPath.isErase = true;\n if (this.isDrawing) {\n this.canvasHandler.drawnPaths.push(this.currentPath); // if currently drawing, save the current path to the stack (for undo feature)\n this.isDrawing = false;\n }\n }\n}\n\nexport default DrawingHandler;\n","import BrushHandler from \"./brushHandler\";\nimport ColorHandler from \"./colorHandler\";\nimport DrawingHandler from \"./drawingHandler\";\n\nclass CanvasHandler {\n constructor() {\n this.setupCanvas();\n this.setupCanvasProportions();\n this.setupEraser();\n this.setupUndoBtn();\n this.setupRedoBtn();\n this.setupClearBtn();\n this.setupDownloadBtn();\n\n this.colorHandler = new ColorHandler(this);\n this.brushHandler = new BrushHandler(this, this.colorHandler);\n this.drawingHandler = new DrawingHandler(\n this,\n this.colorHandler,\n this.brushHandler\n );\n }\n\n // setting up the canvas\n setupCanvas() {\n this.canvas = document.getElementById(\"canvas\");\n this.ctx = this.canvas.getContext(\"2d\");\n this.isDrawing = false;\n }\n\n setupCanvasProportions() {\n const topMargin = 100;\n const bottomMargin = 100;\n\n this.canvas.style.position = \"absolute\";\n this.canvas.style.top = topMargin + \"px\";\n\n this.canvas.height = window.innerHeight - topMargin - bottomMargin;\n this.canvas.width = window.innerWidth;\n }\n\n setupClearBtn() {\n this.clearBtn = document.getElementById(\"clear\");\n this.clearBtn.addEventListener(\"click\", () => this.clear());\n }\n\n setupEraser() {\n this.eraserCheckbox = document.getElementById(\"eraser\");\n }\n\n setupUndoBtn() {\n this.drawnPaths = [];\n this.undoBtn = document.getElementById(\"undo\");\n this.undoBtn.addEventListener(\"click\", () => this.undo());\n }\n\n setupRedoBtn() {\n this.redoStack = [];\n this.redoBtn = document.getElementById(\"redo\");\n this.redoBtn.addEventListener(\"click\", () => this.redo());\n }\n\n setupDownloadBtn() {\n this.downloadBtn = document.getElementById(\"download\");\n this.downloadBtn.addEventListener(\"click\", () => this.download());\n }\n\n // btn actions\n clear() {\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n this.canvas.style.backgroundColor = \"white\";\n this.redoStack = [];\n this.drawnPaths = [];\n }\n\n undo() {\n // if there are paths in the stack\n if (this.drawnPaths.length > 0) {\n // clear canvas (to prep for redraw)\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n // remove (undo) last drawn path from the stack\n const undonePath = this.drawnPaths.pop();\n // push the undone path to redo stack\n this.drawingHandler.redoStack.push(undonePath);\n\n // redraw all paths that are still in the stack\n this.drawnPaths.forEach((path) => this.redrawPath(path));\n }\n }\n\n redrawPath(path) {\n path.forEach((point, idx) => {\n // if it's the starting point of the path\n if (idx === 0) {\n // move to the starting point\n this.ctx.beginPath();\n this.ctx.moveTo(point.x, point.y);\n } else {\n // draw a line to the next point\n this.ctx.lineTo(point.x, point.y);\n\n // set brush styling based on point clr & brush size\n if (path.isErase) point.color = this.colorHandler.bgColorPicker.value;\n this.brushHandler.setBrushStyling(point.color, point.brushSize);\n\n this.ctx.stroke();\n }\n });\n }\n\n redo() {\n // if there are paths in the redo stack\n if (this.drawingHandler.redoStack.length > 0) {\n // clear canvas (to prep for redraw)\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n // remove (redo) last undone path from the redo stack\n const redonePath = this.drawingHandler.redoStack.pop();\n // push the redone path to drawnPaths stack\n this.drawnPaths.push(redonePath);\n\n // redraw all paths with the correct color\n this.drawnPaths.forEach((path) => this.redrawPath(path));\n }\n }\n\n download() {\n // create a temp canvas to preserve the background (wo this the bg would be transparent)\n const tempCanvas = document.createElement(\"canvas\");\n const tempCtx = tempCanvas.getContext(\"2d\");\n tempCanvas.width = this.canvas.width;\n tempCanvas.height = this.canvas.height;\n\n // set the background color on the temp canvas\n tempCtx.fillStyle = this.canvas.style.backgroundColor;\n tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);\n\n // draw the existing canvas content on top of the background \n tempCtx.drawImage(this.canvas, 0, 0);\n\n // get the data URL of the temp canvas\n const dataUrl = tempCanvas.toDataURL(\"image/png\");\n\n // create a link ele for download\n const link = document.createElement(\"a\");\n link.href = dataUrl;\n link.download = \"canvas.png\";\n\n // trigger the download\n link.click();\n }\n}\n\nexport default CanvasHandler;\n","class ToolIcon {\n constructor() {\n this.brushRadio = document.getElementById(\"brush\");\n this.eraserRadio = document.getElementById(\"eraser\");\n this.brushLabel = document.querySelector('label[for=\"brush\"]');\n this.eraserLabel = document.querySelector('label[for=\"eraser\"]');\n this.detectChange();\n this.updateIcon();\n }\n\n updateIcon() {\n // update brush icon based on whether the brush is checked\n this.brushLabel.querySelector(\"img\").src = this.brushRadio.checked\n ? \"assets/tab-icon.png\"\n : \"assets/menu icons/not-active-brush.png\";\n\n // update eraser icon based on whether the eraser is checked\n this.eraserLabel.querySelector(\"img\").src = this.eraserRadio.checked\n ? \"assets/menu icons/active-eraser.png\"\n : \"assets/menu icons/not-active-eraser.png\";\n }\n\n detectChange() {\n // update icon clr when tool is changed\n [this.brushRadio, this.eraserRadio].forEach((radio) => {\n radio.addEventListener(\"change\", () => this.updateIcon());\n });\n }\n}\n\nexport default ToolIcon;\n","import CanvasHandler from \"./scripts/canvasHandler\";\nimport ToolIcon from \"./scripts/toolIcon\";\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n new CanvasHandler();\n new ToolIcon();\n});\n\n\n\n\n\n\n\n\n"],"names":["constructor","canvasHandler","this","setupBrushSize","brushSizeInput","document","getElementById","addEventListener","updateBrushSize","currentBrushSize","setBrushStyling","color","arguments","length","undefined","colorHandler","currentColor","brushSize","ctx","lineCap","lineWidth","strokeStyle","parseInt","value","setupColorHandling","brushColorPicker","bgColorPicker","drawnPaths","redoStack","clear","forEach","path","redrawPath","canvas","style","backgroundColor","brushHandler","setupDrawingEventListeners","e","startDrawing","draw","stopDrawing","isDrawing","currentPath","canvasMouseX","clientX","offsetLeft","canvasMouseY","clientY","offsetTop","beginPath","moveTo","push","x","y","mouseX","mouseY","lineTo","eraserCheckbox","checked","stroke","isErase","setupCanvas","setupCanvasProportions","setupEraser","setupUndoBtn","setupRedoBtn","setupClearBtn","setupDownloadBtn","ColorHandler","BrushHandler","drawingHandler","DrawingHandler","getContext","position","top","topMargin","height","window","innerHeight","width","innerWidth","clearBtn","undoBtn","undo","redoBtn","redo","downloadBtn","download","clearRect","undonePath","pop","point","idx","redonePath","tempCanvas","createElement","tempCtx","fillStyle","fillRect","drawImage","dataUrl","toDataURL","link","href","click","brushRadio","eraserRadio","brushLabel","querySelector","eraserLabel","detectChange","updateIcon","src","radio","CanvasHandler","ToolIcon"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"main.js","mappings":"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","sources":["webpack://canvas-project/./src/scripts/brushHandler.js","webpack://canvas-project/./src/scripts/colorHandler.js","webpack://canvas-project/./src/scripts/drawingHandler.js","webpack://canvas-project/./src/scripts/canvasHandler.js","webpack://canvas-project/./src/scripts/toolIcon.js","webpack://canvas-project/./src/index.js"],"sourcesContent":["class BrushHandler {\n constructor(canvasHandler) {\n this.canvasHandler = canvasHandler;\n this.setupBrushSize();\n }\n\n setupBrushSize() {\n this.brushSizeInput = document.getElementById(\"size-slider\");\n this.brushSizeInput.addEventListener(\"input\", () => this.updateBrushSize());\n this.currentBrushSize = 5;\n }\n\n setBrushStyling(\n color = this.canvasHandler.colorHandler.currentColor,\n brushSize = this.currentBrushSize\n ) {\n this.canvasHandler.ctx.lineCap = \"round\";\n this.canvasHandler.ctx.lineWidth = brushSize;\n this.canvasHandler.ctx.strokeStyle = color;\n }\n\n updateBrushSize() {\n this.currentBrushSize = parseInt(this.brushSizeInput.value);\n this.setBrushStyling();\n }\n // dotted brush, glitter brush?\n}\n\nexport default BrushHandler;\n","class ColorHandler {\n constructor(canvasHandler) {\n this.setupColorHandling()\n this.canvasHandler = canvasHandler\n }\n\n setupColorHandling() {\n this.currentColor = \"black\";\n\n // if a brush color has been selected..\n this.brushColorPicker = document.getElementById(\"color-picker\");\n\n this.brushColorPicker.addEventListener(\"input\", () => {\n this.currentColor = this.brushColorPicker.value;\n });\n\n // if a bg color has been selected..\n this.bgColorPicker = document.getElementById(\"background-color-picker\");\n this.bgColorPicker.addEventListener(\n \"input\",\n () => {\n const drawnPaths = this.canvasHandler.drawnPaths\n const redoStack = this.canvasHandler.redoStack\n this.canvasHandler.clear()\n this.canvasHandler.drawnPaths = drawnPaths\n this.canvasHandler.redoStack = redoStack\n drawnPaths.forEach((path) => this.canvasHandler.redrawPath(path));\n this.canvasHandler.canvas.style.backgroundColor = this.bgColorPicker.value;\n }\n );\n }\n}\n\nexport default ColorHandler","class DrawingHandler {\n constructor(canvasHandler, colorHandler) {\n this.canvasHandler = canvasHandler;\n this.colorHandler = colorHandler;\n this.setupDrawingEventListeners();\n }\n\n setupDrawingEventListeners() {\n this.canvasHandler.canvas.addEventListener(\"mousedown\", (e) => this.startDrawing(e));\n this.canvasHandler.canvas.addEventListener(\"mousemove\", (e) => this.draw(e));\n this.canvasHandler.canvas.addEventListener(\"mouseup\", () => this.stopDrawing());\n this.canvasHandler.canvas.addEventListener(\"mouseout\", () => this.stopDrawing());\n }\n\n // // drawing actions\n startDrawing(e) {\n if (!this.isDrawing) {\n // clear the stacks when a new drawing begins\n this.currentPath = [];\n this.redoStack = [];\n this.isDrawing = true;\n }\n\n // calculate the adjusted mouse coordinates relative to the canvas\n const canvasMouseX = e.clientX - this.canvasHandler.canvas.offsetLeft;\n const canvasMouseY = e.clientY - this.canvasHandler.canvas.offsetTop;\n\n // begin a new path in the canvas ctx & move to initial drawing pos\n this.canvasHandler.ctx.beginPath();\n\n // move the brush to the adjusted mouse coordinates\n this.canvasHandler.ctx.moveTo(canvasMouseX, canvasMouseY);\n\n // store the starting point in the drawing path\n this.currentPath.push({\n x: canvasMouseX,\n y: canvasMouseY,\n color: this.colorHandler.currentColor,\n brushSize: this.canvasHandler.brushHandler.currentBrushSize,\n });\n\n // draw a dot at the starting point\n this.draw(e);\n }\n\n draw(e) {\n if (!this.isDrawing) return;\n\n // calculate the adjusted mouse coordinates relative to the canvas\n const mouseX = e.clientX - this.canvasHandler.canvas.offsetLeft;\n const mouseY = e.clientY - this.canvasHandler.canvas.offsetTop;\n\n // connect the current drawing position to the new position\n this.canvasHandler.ctx.lineTo(mouseX, mouseY);\n\n // Set brush styling based on whether eraser or brush is checked\n const color = this.canvasHandler.eraserCheckbox.checked\n ? this.colorHandler.bgColorPicker.value\n : this.colorHandler.currentColor;\n\n this.canvasHandler.brushHandler.setBrushStyling(\n color,\n this.canvasHandler.brushHandler.currentBrushSize\n );\n\n // draw the line on the canvas\n this.canvasHandler.ctx.stroke();\n\n // store the current point in the drawing path\n this.currentPath.push({\n x: mouseX,\n y: mouseY,\n color: color,\n brushSize: this.canvasHandler.brushHandler.currentBrushSize,\n });\n }\n\n stopDrawing() {\n if (this.canvasHandler.eraserCheckbox.checked)\n this.currentPath.isErase = true;\n if (this.isDrawing) {\n this.canvasHandler.drawnPaths.push(this.currentPath); // if currently drawing, save the current path to the stack (for undo feature)\n this.isDrawing = false;\n }\n }\n}\n\nexport default DrawingHandler;\n","import BrushHandler from \"./brushHandler\";\nimport ColorHandler from \"./colorHandler\";\nimport DrawingHandler from \"./drawingHandler\";\n\nclass CanvasHandler {\n constructor() {\n this.setupCanvas();\n this.setupCanvasProportions();\n this.setupEraser();\n this.setupUndoBtn();\n this.setupRedoBtn();\n this.setupClearBtn();\n this.setupDownloadBtn();\n\n this.colorHandler = new ColorHandler(this);\n this.brushHandler = new BrushHandler(this);\n this.drawingHandler = new DrawingHandler(\n this,\n this.colorHandler\n );\n }\n\n // setting up the canvas\n setupCanvas() {\n this.canvas = document.getElementById(\"canvas\");\n this.ctx = this.canvas.getContext(\"2d\");\n this.isDrawing = false;\n }\n\n setupCanvasProportions() {\n const topMargin = 100;\n const bottomMargin = 100;\n\n this.canvas.style.position = \"absolute\";\n this.canvas.style.top = topMargin + \"px\";\n\n this.canvas.height = window.innerHeight - topMargin - bottomMargin;\n this.canvas.width = window.innerWidth;\n }\n\n setupClearBtn() {\n this.clearBtn = document.getElementById(\"clear\");\n this.clearBtn.addEventListener(\"click\", () => this.clear());\n }\n\n setupEraser() {\n this.eraserCheckbox = document.getElementById(\"eraser\");\n }\n\n setupUndoBtn() {\n this.drawnPaths = [];\n this.undoBtn = document.getElementById(\"undo\");\n this.undoBtn.addEventListener(\"click\", () => this.undo());\n }\n\n setupRedoBtn() {\n this.redoStack = [];\n this.redoBtn = document.getElementById(\"redo\");\n this.redoBtn.addEventListener(\"click\", () => this.redo());\n }\n\n setupDownloadBtn() {\n this.downloadBtn = document.getElementById(\"download\");\n this.downloadBtn.addEventListener(\"click\", () => this.download());\n }\n\n // btn actions\n clear() {\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n this.canvas.style.backgroundColor = \"white\";\n this.redoStack = [];\n this.drawnPaths = [];\n }\n\n undo() {\n // if there are paths in the stack\n if (this.drawnPaths.length > 0) {\n // clear canvas (to prep for redraw)\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n // remove (undo) last drawn path from the stack\n const undonePath = this.drawnPaths.pop();\n // push the undone path to redo stack\n this.drawingHandler.redoStack.push(undonePath);\n\n // redraw all paths that are still in the stack\n this.drawnPaths.forEach((path) => this.redrawPath(path));\n }\n }\n\n redrawPath(path) {\n path.forEach((point, idx) => {\n // if it's the starting point of the path\n if (idx === 0) {\n // move to the starting point\n this.ctx.beginPath();\n this.ctx.moveTo(point.x, point.y);\n } else {\n // draw a line to the next point\n this.ctx.lineTo(point.x, point.y);\n\n // set brush styling based on point clr & brush size\n if (path.isErase) point.color = this.colorHandler.bgColorPicker.value;\n this.brushHandler.setBrushStyling(point.color, point.brushSize);\n\n this.ctx.stroke();\n }\n });\n }\n\n redo() {\n // if there are paths in the redo stack\n if (this.drawingHandler.redoStack.length > 0) {\n // clear canvas (to prep for redraw)\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n // remove (redo) last undone path from the redo stack\n const redonePath = this.drawingHandler.redoStack.pop();\n // push the redone path to drawnPaths stack\n this.drawnPaths.push(redonePath);\n\n // redraw all paths with the correct color\n this.drawnPaths.forEach((path) => this.redrawPath(path));\n }\n }\n\n download() {\n // create a temp canvas to preserve the background (wo this the bg would be transparent)\n const tempCanvas = document.createElement(\"canvas\");\n const tempCtx = tempCanvas.getContext(\"2d\");\n tempCanvas.width = this.canvas.width;\n tempCanvas.height = this.canvas.height;\n\n // set the background color on the temp canvas\n tempCtx.fillStyle = this.canvas.style.backgroundColor;\n tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);\n\n // draw the existing canvas content on top of the background \n tempCtx.drawImage(this.canvas, 0, 0);\n\n // get the data URL of the temp canvas\n const dataUrl = tempCanvas.toDataURL(\"image/png\");\n\n // create a link ele for download\n const link = document.createElement(\"a\");\n link.href = dataUrl;\n link.download = \"canvas.png\";\n\n // trigger the download\n link.click();\n }\n}\n\nexport default CanvasHandler;\n","class ToolIcon {\n constructor() {\n this.brushRadio = document.getElementById(\"brush\");\n this.eraserRadio = document.getElementById(\"eraser\");\n this.brushLabel = document.querySelector('label[for=\"brush\"]');\n this.eraserLabel = document.querySelector('label[for=\"eraser\"]');\n this.detectChange();\n this.updateIcon();\n }\n\n updateIcon() {\n // update brush icon based on whether the brush is checked\n this.brushLabel.querySelector(\"img\").src = this.brushRadio.checked\n ? \"assets/tab-icon.png\"\n : \"assets/menu icons/not-active-brush.png\";\n\n // update eraser icon based on whether the eraser is checked\n this.eraserLabel.querySelector(\"img\").src = this.eraserRadio.checked\n ? \"assets/menu icons/active-eraser.png\"\n : \"assets/menu icons/not-active-eraser.png\";\n }\n\n detectChange() {\n // update icon clr when tool is changed\n [this.brushRadio, this.eraserRadio].forEach((radio) => {\n radio.addEventListener(\"change\", () => this.updateIcon());\n });\n }\n}\n\nexport default ToolIcon;\n","import CanvasHandler from \"./scripts/canvasHandler\";\nimport ToolIcon from \"./scripts/toolIcon\";\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n new CanvasHandler();\n new ToolIcon();\n});\n\n\n\n\n\n\n\n\n"],"names":["constructor","canvasHandler","this","setupBrushSize","brushSizeInput","document","getElementById","addEventListener","updateBrushSize","currentBrushSize","setBrushStyling","color","arguments","length","undefined","colorHandler","currentColor","brushSize","ctx","lineCap","lineWidth","strokeStyle","parseInt","value","setupColorHandling","brushColorPicker","bgColorPicker","drawnPaths","redoStack","clear","forEach","path","redrawPath","canvas","style","backgroundColor","setupDrawingEventListeners","e","startDrawing","draw","stopDrawing","isDrawing","currentPath","canvasMouseX","clientX","offsetLeft","canvasMouseY","clientY","offsetTop","beginPath","moveTo","push","x","y","brushHandler","mouseX","mouseY","lineTo","eraserCheckbox","checked","stroke","isErase","setupCanvas","setupCanvasProportions","setupEraser","setupUndoBtn","setupRedoBtn","setupClearBtn","setupDownloadBtn","ColorHandler","BrushHandler","drawingHandler","DrawingHandler","getContext","position","top","topMargin","height","window","innerHeight","width","innerWidth","clearBtn","undoBtn","undo","redoBtn","redo","downloadBtn","download","clearRect","undonePath","pop","point","idx","redonePath","tempCanvas","createElement","tempCtx","fillStyle","fillRect","drawImage","dataUrl","toDataURL","link","href","click","brushRadio","eraserRadio","brushLabel","querySelector","eraserLabel","detectChange","updateIcon","src","radio","CanvasHandler","ToolIcon"],"sourceRoot":""} \ No newline at end of file diff --git a/src/scripts/canvasHandler.js b/src/scripts/canvasHandler.js index 74a4f40..804d365 100644 --- a/src/scripts/canvasHandler.js +++ b/src/scripts/canvasHandler.js @@ -13,11 +13,10 @@ class CanvasHandler { this.setupDownloadBtn(); this.colorHandler = new ColorHandler(this); - this.brushHandler = new BrushHandler(this, this.colorHandler); + this.brushHandler = new BrushHandler(this); this.drawingHandler = new DrawingHandler( this, - this.colorHandler, - this.brushHandler + this.colorHandler ); } diff --git a/src/scripts/drawingHandler.js b/src/scripts/drawingHandler.js index 47b4b6b..d570f81 100644 --- a/src/scripts/drawingHandler.js +++ b/src/scripts/drawingHandler.js @@ -1,17 +1,15 @@ class DrawingHandler { - constructor(canvasHandler, colorHandler, brushHandler) { + constructor(canvasHandler, colorHandler) { this.canvasHandler = canvasHandler; - this.canvas = this.canvasHandler.canvas; this.colorHandler = colorHandler; - this.brushHandler = brushHandler; this.setupDrawingEventListeners(); } setupDrawingEventListeners() { - this.canvas.addEventListener("mousedown", (e) => this.startDrawing(e)); - this.canvas.addEventListener("mousemove", (e) => this.draw(e)); - this.canvas.addEventListener("mouseup", () => this.stopDrawing()); - this.canvas.addEventListener("mouseout", () => this.stopDrawing()); + this.canvasHandler.canvas.addEventListener("mousedown", (e) => this.startDrawing(e)); + this.canvasHandler.canvas.addEventListener("mousemove", (e) => this.draw(e)); + this.canvasHandler.canvas.addEventListener("mouseup", () => this.stopDrawing()); + this.canvasHandler.canvas.addEventListener("mouseout", () => this.stopDrawing()); } // // drawing actions @@ -24,8 +22,8 @@ class DrawingHandler { } // calculate the adjusted mouse coordinates relative to the canvas - const canvasMouseX = e.clientX - this.canvas.offsetLeft; - const canvasMouseY = e.clientY - this.canvas.offsetTop; + const canvasMouseX = e.clientX - this.canvasHandler.canvas.offsetLeft; + const canvasMouseY = e.clientY - this.canvasHandler.canvas.offsetTop; // begin a new path in the canvas ctx & move to initial drawing pos this.canvasHandler.ctx.beginPath(); @@ -38,7 +36,7 @@ class DrawingHandler { x: canvasMouseX, y: canvasMouseY, color: this.colorHandler.currentColor, - brushSize: this.brushHandler.currentBrushSize, + brushSize: this.canvasHandler.brushHandler.currentBrushSize, }); // draw a dot at the starting point @@ -49,8 +47,8 @@ class DrawingHandler { if (!this.isDrawing) return; // calculate the adjusted mouse coordinates relative to the canvas - const mouseX = e.clientX - this.canvas.offsetLeft; - const mouseY = e.clientY - this.canvas.offsetTop; + const mouseX = e.clientX - this.canvasHandler.canvas.offsetLeft; + const mouseY = e.clientY - this.canvasHandler.canvas.offsetTop; // connect the current drawing position to the new position this.canvasHandler.ctx.lineTo(mouseX, mouseY); @@ -60,9 +58,9 @@ class DrawingHandler { ? this.colorHandler.bgColorPicker.value : this.colorHandler.currentColor; - this.brushHandler.setBrushStyling( + this.canvasHandler.brushHandler.setBrushStyling( color, - this.brushHandler.currentBrushSize + this.canvasHandler.brushHandler.currentBrushSize ); // draw the line on the canvas @@ -73,7 +71,7 @@ class DrawingHandler { x: mouseX, y: mouseY, color: color, - brushSize: this.brushHandler.currentBrushSize, + brushSize: this.canvasHandler.brushHandler.currentBrushSize, }); }