Initializing
Liveweave
Web
expand_more
home
Home
data_object
CSS Explorer
arrow_outward
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
outbox_alt
Generative AI
arrow_outward
frame_source
Python Playground
New
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Save
account_circle
Login
settings
Settings
expand_more
14
px
Live mode
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
<!DOCTYPE html> <!-- Coding By CodingNepal - youtube.com/codingnepal --> <html lang="en" dir="ltr"> <head> <meta charset="utf-8"> <title>Drawing App in JavaScript</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <div class="container"> <section class="tools-board"> <div class="row"> <label class="title">Shapes</label> <ul class="options"> <li class="option tool" id="rectangle"> <img src="icons/rectangle.svg" alt=""> <span>Rectangle</span> </li> <li class="option tool" id="circle"> <img src="icons/circle.svg" alt=""> <span>Circle</span> </li> <li class="option tool" id="triangle"> <img src="icons/triangle.svg" alt=""> <span>Triangle</span> </li> <li class="option"> <input type="checkbox" id="fill-color"> <label for="fill-color">Fill color</label> </li> </ul> </div> <div class="row"> <label class="title">Options</label> <ul class="options"> <li class="option active tool" id="brush"> <img src="icons/brush.svg" alt=""> <span>Brush</span> </li> <li class="option tool" id="eraser"> <img src="icons/eraser.svg" alt=""> <span>Eraser</span> </li> <li class="option"> <input type="range" id="size-slider" min="1" max="30" value="5"> </li> </ul> </div> <div class="row colors"> <label class="title">Colors</label> <ul class="options"> <li class="option"></li> <li class="option selected"></li> <li class="option"></li> <li class="option"></li> <li class="option"> <input type="color" id="color-picker" value="#4A98F7"> </li> </ul> </div> <div class="row buttons"> <button class="clear-canvas">Clear Canvas</button> <button class="save-img">Save As Image</button> </div> </section> <section class="drawing-board"> <canvas></canvas> </section> </div> </body> </html>
/* Import Google font - Poppins */ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap'); *{ margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', sans-serif; } body{ display: flex; align-items: center; justify-content: center; min-height: 100vh; background: #4A98F7; } .container{ display: flex; width: 100%; gap: 10px; padding: 10px; max-width: 1050px; } section{ background: #fff; border-radius: 7px; } .tools-board{ width: 210px; padding: 15px 22px 0; } .tools-board .row{ margin-bottom: 20px; } .row .options{ list-style: none; margin: 10px 0 0 5px; } .row .options .option{ display: flex; cursor: pointer; align-items: center; margin-bottom: 10px; } .option:is(:hover, .active) img{ filter: invert(17%) sepia(90%) saturate(3000%) hue-rotate(900deg) brightness(100%) contrast(100%); } .option :where(span, label){ color: #5A6168; cursor: pointer; padding-left: 10px; } .option:is(:hover, .active) :where(span, label){ color: #4A98F7; } .option #fill-color{ cursor: pointer; height: 14px; width: 14px; } #fill-color:checked ~ label{ color: #4A98F7; } .option #size-slider{ width: 100%; height: 5px; margin-top: 10px; } .colors .options{ display: flex; justify-content: space-between; } .colors .option{ height: 20px; width: 20px; border-radius: 50%; margin-top: 3px; position: relative; } .colors .option:nth-child(1){ background-color: #fff; border: 1px solid #bfbfbf; } .colors .option:nth-child(2){ background-color: #000; } .colors .option:nth-child(3){ background-color: #E02020; } .colors .option:nth-child(4){ background-color: #6DD400; } .colors .option:nth-child(5){ background-color: #4A98F7; } .colors .option.selected::before{ position: absolute; content: ""; top: 50%; left: 50%; height: 12px; width: 12px; background: inherit; border-radius: inherit; border: 2px solid #fff; transform: translate(-50%, -50%); } .colors .option:first-child.selected::before{ border-color: #ccc; } .option #color-picker{ opacity: 0; cursor: pointer; } .buttons button{ width: 100%; color: #fff; border: none; outline: none; padding: 11px 0; font-size: 0.9rem; margin-bottom: 13px; background: none; border-radius: 4px; cursor: pointer; } .buttons .clear-canvas{ color: #6C757D; border: 1px solid #6C757D; transition: all 0.3s ease; } .clear-canvas:hover{ color: #fff; background: #6C757D; } .buttons .save-img{ background: #4A98F7; border: 1px solid #4A98F7; } .drawing-board{ flex: 1; overflow: hidden; } .drawing-board canvas{ width: 100%; height: 100%; }
const canvas = document.querySelector("canvas"), toolBtns = document.querySelectorAll(".tool"), fillColor = document.querySelector("#fill-color"), sizeSlider = document.querySelector("#size-slider"), colorBtns = document.querySelectorAll(".colors .option"), colorPicker = document.querySelector("#color-picker"), clearCanvas = document.querySelector(".clear-canvas"), saveImg = document.querySelector(".save-img"), ctx = canvas.getContext("2d"); // global variables with default value let prevMouseX, prevMouseY, snapshot, isDrawing = false, selectedTool = "brush", brushWidth = 5, selectedColor = "#000"; const setCanvasBackground = () => { // setting whole canvas background to white, so the downloaded img background will be white ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = selectedColor; // setting fillstyle back to the selectedColor, it'll be the brush color } window.addEventListener("load", () => { // setting canvas width/height.. offsetwidth/height returns viewable width/height of an element canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; setCanvasBackground(); }); const drawRect = (e) => { // if fillColor isn't checked draw a rect with border else draw rect with background if(!fillColor.checked) { // creating circle according to the mouse pointer return ctx.strokeRect(e.offsetX, e.offsetY, prevMouseX - e.offsetX, prevMouseY - e.offsetY); } ctx.fillRect(e.offsetX, e.offsetY, prevMouseX - e.offsetX, prevMouseY - e.offsetY); } const drawCircle = (e) => { ctx.beginPath(); // creating new path to draw circle // getting radius for circle according to the mouse pointer let radius = Math.sqrt(Math.pow((prevMouseX - e.offsetX), 2) + Math.pow((prevMouseY - e.offsetY), 2)); ctx.arc(prevMouseX, prevMouseY, radius, 0, 2 * Math.PI); // creating circle according to the mouse pointer fillColor.checked ? ctx.fill() : ctx.stroke(); // if fillColor is checked fill circle else draw border circle } const drawTriangle = (e) => { ctx.beginPath(); // creating new path to draw circle ctx.moveTo(prevMouseX, prevMouseY); // moving triangle to the mouse pointer ctx.lineTo(e.offsetX, e.offsetY); // creating first line according to the mouse pointer ctx.lineTo(prevMouseX * 2 - e.offsetX, e.offsetY); // creating bottom line of triangle ctx.closePath(); // closing path of a triangle so the third line draw automatically fillColor.checked ? ctx.fill() : ctx.stroke(); // if fillColor is checked fill triangle else draw border } const startDraw = (e) => { isDrawing = true; prevMouseX = e.offsetX; // passing current mouseX position as prevMouseX value prevMouseY = e.offsetY; // passing current mouseY position as prevMouseY value ctx.beginPath(); // creating new path to draw ctx.lineWidth = brushWidth; // passing brushSize as line width ctx.strokeStyle = selectedColor; // passing selectedColor as stroke style ctx.fillStyle = selectedColor; // passing selectedColor as fill style // copying canvas data & passing as snapshot value.. this avoids dragging the image snapshot = ctx.getImageData(0, 0, canvas.width, canvas.height); } const drawing = (e) => { if(!isDrawing) return; // if isDrawing is false return from here ctx.putImageData(snapshot, 0, 0); // adding copied canvas data on to this canvas if(selectedTool === "brush" || selectedTool === "eraser") { // if selected tool is eraser then set strokeStyle to white // to paint white color on to the existing canvas content else set the stroke color to selected color ctx.strokeStyle = selectedTool === "eraser" ? "#fff" : selectedColor; ctx.lineTo(e.offsetX, e.offsetY); // creating line according to the mouse pointer ctx.stroke(); // drawing/filling line with color } else if(selectedTool === "rectangle"){ drawRect(e); } else if(selectedTool === "circle"){ drawCircle(e); } else { drawTriangle(e); } } toolBtns.forEach(btn => { btn.addEventListener("click", () => { // adding click event to all tool option // removing active class from the previous option and adding on current clicked option document.querySelector(".options .active").classList.remove("active"); btn.classList.add("active"); selectedTool = btn.id; }); }); sizeSlider.addEventListener("change", () => brushWidth = sizeSlider.value); // passing slider value as brushSize colorBtns.forEach(btn => { btn.addEventListener("click", () => { // adding click event to all color button // removing selected class from the previous option and adding on current clicked option document.querySelector(".options .selected").classList.remove("selected"); btn.classList.add("selected"); // passing selected btn background color as selectedColor value selectedColor = window.getComputedStyle(btn).getPropertyValue("background-color"); }); }); colorPicker.addEventListener("change", () => { // passing picked color value from color picker to last color btn background colorPicker.parentElement.style.background = colorPicker.value; colorPicker.parentElement.click(); }); clearCanvas.addEventListener("click", () => { ctx.clearRect(0, 0, canvas.width, canvas.height); // clearing whole canvas setCanvasBackground(); }); saveImg.addEventListener("click", () => { const link = document.createElement("a"); // creating <a> element link.download = `${Date.now()}.jpg`; // passing current date as link download value link.href = canvas.toDataURL(); // passing canvasData as link href value link.click(); // clicking link to download image }); canvas.addEventListener("mousedown", startDraw); canvas.addEventListener("mousemove", drawing); canvas.addEventListener("mouseup", () => isDrawing = false);