<div id="container_div">
  <div id="palette_div">
    <div id="slider_track"></div>
    <div id="slider">
      <img id="slider_icon" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/409445/drawing_app_slider_icon.svg">
    <div id="slider_mask"></div>
    </div>
    <div class="color" id="red" style="background:red"></div>
    <div class="color" id="purple" style="background:purple"></div>
    <div class="color" id="blue" style="background:blue"></div>
    <div class="color" id="green" style="background:green"></div>
    <div class="color" id="yellow" style="background:yellow"></div>
    <div class="color" id="orange" style="background:orange"></div>
    <div class="color" id="black" style="background:black"></div>
    <div class="color" id="gray" style="background:gray"></div>
    <div class="color" id="white" style="background:white"></div>
  </div>
  <div id="canvas_div">
    <canvas id="sheet"></canvas>
  </div>
  <div id="footer_div">
    <a id="clear" class="buttons">
      <img class="footer_icons" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/409445/drawing_app_clear_icon.svg">
    </a>
    <a id="save" class="buttons">
      <img class="footer_icons" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/409445/drawing_app_download_icon.svg">
    </a>
  </div>
</div> 


#container_div {
  position: absolute;
  right: 50%;
  top: 48.5%;
  transform: translate(50%,-50%);
}

#palette_div {
  position: absolute;
  width: 100%;
  height: 20%; 
  background: #E5E5E5;
  box-shadow: 0 0 2px 1px rgba(0,0,0,.4);
}

#slider_track {
  position: relative;
  width: 94%;
  margin: auto;
  height: 4%;
  top: 18%;
  border-radius: 100px;
  box-shadow: inset 0 0 2px 1px rgba(0,0,0,.4);
}

#slider {
  position: absolute;
  width: 5%;
  height: 15%;
  top: 12%;
  left: 2%;
  border-radius: 100px;
  background: #E5E5E5;
  box-shadow: 0 0 2px 1px rgba(0,0,0,.4);
  cursor: pointer;
} 

#slider_icon {
  position: absolute;
  width: 50%;
  right: 50%;
  top: 50%;
  transform: translate(50%,-50%);
  user-select: none;  /* prevents browser from highlighting the icon when sliding */
}

/* a transparent surface that prevents browser from grabbing the icon when sliding */
#slider_mask {
  position: relative;
  width: 100%;
  height: 100%;
  opacity: 0;
}

.color {
  position: relative; 
  float: left; 
  height: 47%;
  width: 9%;
  top: 36%;
  margin-left: 1.9%;
  border-radius: 6px;
  box-shadow: inset 0 0 2px 1px rgba(0,0,0,.6);
  cursor: pointer;
}
.color:hover {
  box-shadow: inset 0 0 2px 1px rgba(0,0,0,.6), inset 0 0 20px 8px rgba(0,0,0,.25);
}
#black:hover {
  box-shadow: inset 0 0 2px 1px rgba(0,0,0,.6), inset 0 0 40px 15px rgba(255,255,255,.2);
}

#canvas_div {
  position: absolute;
  bottom: 0px;
  width: 100%;
  height: 78%;
  box-shadow: 0 0 2px 1px rgba(0,0,0,.35);
}

#footer_div {
  position: absolute;
  bottom: -6%;
  width: 100%;
  height: 4%;
}

.buttons {
  position: absolute;
  width: 8%;
  height: 100%;
  border-radius: 100px;
  box-shadow: 0 0 2px 1px rgba(0,0,0,.3);
  background: #E5E5E5;
}

.buttons:hover {
  background: #E0E0E0;
}

.buttons:hover > .footer_icons {
  opacity: 1;
}

#clear {
  left: 0;
}

#save {
  right: 0;
}

.footer_icons {
  position: absolute;
  width: 23%;
  right: 50%;
  top: 51%;
  transform: translate(50%,-50%);
  opacity: .65;
  cursor: pointer;
}

#save img {
  top: 50%;
  width: 27%;
}
/////////////////////////////////////////////
///      SCALABLE CANVAS PAINTING APP     ///
/////////////////////////////////////////////



///---INITIATION---/// 

//primary variables
var container = document.getElementById("container_div");
var sliderTrack = document.getElementById("slider_track");
var slider = document.getElementById("slider");
var canvas = document.getElementById("sheet");
var ctx = canvas.getContext("2d");

//scale to window size
resizeForWindow();
var canvasPositionLeft = canvas.getBoundingClientRect().left + window.scrollX;
var canvasPositionTop = canvas.getBoundingClientRect().top + window.scrollY;

//prep slider
var mouseX;
var sliderLeft = $("#slider").position().left;
var sliderLeftMin = sliderLeft;
var sliderLeftMax = sliderLeft + $("#slider_track").width()*.965;
var currentlySliding = false;

//prep canvas for downloads with a white background
clearCanvas();

//prep markers
var markerWidth = 2;  // min = 2, max = 100
ctx.lineWidth = markerWidth;

//colors
var colors = document.getElementsByClassName("color");  //an HTMLCollection of .class elements
var currentColor = "black";

//prep drawing
var currentlyDrawing = false;



///---FUNCTIONS---///

//scaling
function resizeForWindow() {
  if (window.innerWidth > window.innerHeight) {
    container.style.height = window.innerHeight*.8+"px";
    container.style.width = container.style.height;
  } else {
    container.style.width = window.innerWidth*.8+"px";
    container.style.height = container.style.width;
  }
  canvas.width = document.getElementById("canvas_div").clientWidth;
  canvas.height = document.getElementById("canvas_div").clientHeight;
  canvasPositionLeft = canvas.getBoundingClientRect().left + window.scrollX;
  canvasPositionTop = canvas.getBoundingClientRect().top + window.scrollY;
  clearCanvas();
  slider.style.left = "2%";
  sliderLeft = $("#slider").position().left;
  sliderLeftMin = sliderLeft;
  sliderLeftMax = sliderLeft + $("#slider_track").width()*.965;
}

//slider
function grab_slider(e) {
  mouseX = e.pageX;
  currentlySliding = true;                                    
}

function drag_slider(e) {
  if (currentlySliding) {
    var mouseXChange = e.pageX - mouseX;
    if (sliderLeft + mouseXChange < sliderLeftMin) {
      slider.style.left = sliderLeftMin + "px";
    } else if (sliderLeft + mouseXChange > sliderLeftMax) {
      slider.style.left = sliderLeftMax + "px";
    } else {
      slider.style.left = (sliderLeft + mouseXChange) + "px";
    };
  }
}

function drop_slider(e) {
  sliderLeft = $("#slider").position().left;
  updateMarker();
  currentlySliding = false;
}

function updateMarker() {
  //converts slider position to a proportional marker width of 2px-100px
  markerWidth = (sliderLeft-sliderLeftMin)*98/(sliderLeftMax-sliderLeftMin-sliderLeftMin)+2;
  ctx.lineWidth = markerWidth;
}

//colors
function bindColors() {
  for (i = 0; i < colors.length; i++) {
    colors[i].addEventListener('click', selectColor);
  }
}

function selectColor(e) {
  currentColor = e.target.style.background;
}

//drawing
function markerDown(e) {
  currentlyDrawing = true;
  var canvasX = e.pageX - canvasPositionLeft;
  var canvasY = e.pageY - canvasPositionTop;
  ctx.beginPath();
  ctx.arc(canvasX, canvasY, markerWidth/2, 0, Math.PI * 2);
  ctx.fillStyle = currentColor;
  ctx.fill();
  ctx.beginPath();
}

function draw(e) {
  var canvasX = e.pageX - canvasPositionLeft;
  var canvasY = e.pageY - canvasPositionTop;
  if(currentlyDrawing) {
    ctx.strokeStyle = currentColor;
    ctx.fillStyle = currentColor;
    ctx.lineTo(canvasX, canvasY);
    ctx.stroke();
    ctx.beginPath();
    ctx.arc(canvasX, canvasY, markerWidth/2, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    ctx.moveTo(canvasX, canvasY); 
  }
}

function markerUp(e) {
  currentlyDrawing = false;
}

//image actions
function saveImage() {
  var image = canvas.toDataURL("image/png");
  var download = document.getElementById("save");
  download.href = image;
  download.download = 'drawing.png';
}

function clearCanvas() {
  ctx.fillStyle = "white";
  ctx.fillRect(0,0,canvas.width, canvas.height);
}



///---EVENTS---///

//window
window.addEventListener('resize', resizeForWindow);

//slider
slider.addEventListener("mousedown", grab_slider);
document.addEventListener("mousemove", drag_slider);
document.addEventListener("mouseup", drop_slider);

slider.addEventListener("touchstart", grab_slider);
document.addEventListener("touchmove", drag_slider);
document.addEventListener("touchend", drop_slider);

//color selection
bindColors();

//drawing
canvas.addEventListener("mousedown", markerDown);
canvas.addEventListener("mousemove", draw);
document.addEventListener("mouseup", markerUp);

canvas.addEventListener("touchstart", markerDown);
canvas.addEventListener("touchmove", draw);
document.addEventListener("touchend", markerUp);

//image actions
document.getElementById("save").addEventListener('click', saveImage);
document.getElementById("clear").addEventListener('click', clearCanvas);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js