<section class="canvas">
 
</section>

<section class="toolbox">
  <div class="canvas-tools">
    <h2>Canvas</h2>
  </div>

  <div class="painting-tools">
    <h2>Painting tools</h2>
  </div>

  <div class="styles-tools">
    <h2>Styles</h2>
  </div>

  <div class="background-tools">
    <h2>Background</h2>
  </div>
</section>

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
<script src="paintbrushes.js"></script>
<script src="app.js"></script>
@import url('https://fonts.googleapis.com/css2?family=Lexend+Deca&family=Nunito&display=swap');

body {
	margin: 0;
	overflow: hidden;
	background-color: #ffffff;

	font-family: Nunito, sans-serif;
	font-size: 14px;
	line-height: 1;
}

section {
	height: 100vh;
	position: fixed;
	top: 0;
}

section.toolbox {
	right: 0;
	width: 180px;
	overflow-y: scroll;

	background-color: white;
	border-left: 1px solid #545454;

	display: flex;
	flex-direction: column;
}

section.canvas {
	left: 0;
	width: calc(100vw - 180px);

	display: flex;
	justify-content: center;
	align-items: center;
}

section.toolbox > div {
	padding: 20px 16px 8px 16px;
	border-bottom: 1px solid #545454;
}

h2 {
	margin-bottom: 24px;

	font-family: Lexend Deca;
	font-size: 14px;
	text-transform: uppercase;
}

label {
	display: block;
	margin-bottom: 8px;
	font-size: 14px;
}

label > * {
	margin-top: 8px;
}

input, button, select {
	font-size: 14px;
	font-family: Nunito, sans-serif;
	line-height: 1;

	width: 100%;
	height: 32px;
	margin-bottom: 12px;

	border: 1px solid #545454;
	border-radius: 4px;
	background-color: #f0f0f0;
}

input:hover, button:hover, select:hover {
	background-color: #dfdfdf;
}

input[type="range"] {
	height: 16px;
}
// set up all the global variables
const toolboxWidth = document.querySelector('section.toolbox').offsetWidth
let canvas = null
let bgColor = '#fbf8f3'

let selectedTool = 'pen'
let brushSelector = null

let paintColor = '#000000'
let ifRainbowColor = false
let opacity = 220

function setup() {
  setupToolbox()

  // set up the canvas
  canvas = createCanvas(windowWidth - toolboxWidth, windowHeight)
  canvas.parent(select('section.canvas'))
  background(bgColor)
}

function setupToolbox() {
  // set up paint style tools in the Styles category
  const paintStyles = select('section.toolbox div.styles-tools')
  setupBrushSelector(paintStyles)
  setupPaintColorPicker(paintStyles)
  setupRainbowColorButton(paintStyles)
  setupOpacitySlider(paintStyles)

  // set up canvas tools in the Canvas category
  const canvasTools = select('section.toolbox div.canvas-tools')
  setupSaveButton(canvasTools)
  setupResetButton(canvasTools)

  // set up background style tools Background category
  const backgroundStyles = select('section.toolbox div.background-tools')
  setupBgColorPicker(backgroundStyles)
}

function setupBrushSelector(parentTag) {
  // create the brush selector as a <select> tag
	brushSelector = createSelect()

  // make a label for the menu
  makeLabel(brushSelector, parentTag, 'Paintbrush style')

  // make an array of all the paintbrush function names
  const brushes = [
    'pen',
    'marker',
    'beads',
    'wiggle',
    'toothpick',
    'fountainPen',
    'splatter',
    'sprayPaint',
  ]

  // add in all of the paintbrush function names as menu options
  brushes.forEach(function (brush) {
      brushSelector.option(brush)
  })

  // set initial value of the currently selected paintbrush
  selectedTool = brushSelector.value()

  // update the selected paintbrush if the user picks a different menu option
  brushSelector.changed(function () {
    selectedTool = brushSelector.value()
  })
}

function makeLabel(tag, parentTag, text) {
  const label = createElement('label', text)
  label.parent(parentTag)
  tag.parent(label)
}

function setupButton(text, parentTag, onClick) {
  const button = createButton(text)
  button.parent(parentTag)
  button.mousePressed(onClick)
  return button
}

function saveFile() {
  saveCanvas('painting', 'png')
}

function setupSaveButton(parentTag) {
  setupButton('Save', parentTag, saveFile)
}

function resetCanvas() {
  // resize canvas to fill the painting area
  resizeCanvas(windowWidth - toolboxWidth, windowHeight)

  // fill canvas with background color
  background(bgColor)
}

function setupResetButton(parentTag) {
  setupButton('Reset', parentTag, resetCanvas)
}

function setupColorPicker(initialColor, parentTag, text, onChange) {
  const colorPicker = createColorPicker(initialColor)
  makeLabel(colorPicker, parentTag, text)
  colorPicker.changed(onChange)
  return colorPicker
}

function setupBgColorPicker(parentTag) {
  const bgColorPicker = setupColorPicker(bgColor, parentTag, 'Background color', function () {
    bgColor = bgColorPicker.color()
    resetCanvas()
  })
}

function setupPaintColorPicker(parentTag) {
  const paintColorPicker = setupColorPicker(paintColor, parentTag, 'Paint color', function () {
    paintColor = paintColorPicker.color()
    ifRainbowColor = false
  })
  paintColor = paintColorPicker.color()
}

function setPaintColor() {
  // set color to either rainbow or normal paint color 
	let newColor
  if (ifRainbowColor) {
    const hue = (frameCount * 2) % 360	
    newColor = color(`hsba(${hue}, 100%, 100%, 0.6)`)
  } else {
		newColor = paintColor
  }

  // set the color and opacity of the stroke and fill
  newColor.setAlpha(opacity)
  stroke(newColor)
  fill(newColor)
}

function setupRainbowColorButton(parentTag) {
  setupButton('Rainbow color 🌈', parentTag, function () {
    ifRainbowColor = true
  })
}

// helper function that sets up a slider
function setupSlider(min, max, initialValue, step, text, parentTag, onInput) {
  const slider = createSlider(min, max, initialValue, step)
  makeLabel(slider, parentTag, text)
  slider.input(onInput)
  return slider
}

function setupOpacitySlider(parentTag) {
  const opacitySlider = setupSlider(0, 255, opacity, 1, 'Opacity', parentTag, function () {
    opacity = opacitySlider.value()
  })
}

function draw() {
	// check if mouse button is pressed and mouse is hovering over canvas section
  if (mouseIsPressed && mouseX <= windowWidth - toolboxWidth) {
    // set the paint color
    setPaintColor()

    // draw on the canvas with the selected painting tool function
    window[selectedTool]()
  }
}

External CSS

  1. https://codepen.io/ninhja/pen/mdmyVgY.css?editors=0110

External JavaScript

  1. https://codepen.io/ninhja/pen/WNjKZGb.js