JSFiddle - React, Tailwind, and code Playground

by Marius Jopen

HTML

<section class="scratchedin">
  <div class="pattern"></div>

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

<section class="scratchedout">
  <div class="lineup">
    <h1>Hover</h1>
    <p class="hoverme" data-info="one">ONE</p>
    <p class="hoverme" data-info="two">TWO</p>
    <p class="hoverme" data-info="three">THREE</p>
  </div>
  
  <div class="hover-info"><h1>INFO</h1></div>

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

CSS

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}

article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
  display: block;
}
body {
  line-height: 1;
}
ol, ul {
  list-style: none;
}
blockquote, q {
  quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}

img, iframe {
  vertical-align: bottom;
  max-width: 100%;
}

input, textarea, select {
  font: inherit;
}

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}





@keyframes bgmove {
  0% {background-position: 0, 0;}
  0% {background-position: -450px, 0;}
}

body {
  height: 100vh;
  overflow: hidden;
  user-select: none;
  
  font-size: 36px;
  line-height: 1.5;
}


canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: transparent;
  
  mix-blend-mode: lighten;
  user-select: none;
  cursor: pointer !important;
}

canvas.out {
  pointer-events:none;
}

canvas.in {
  cursor: pointer !important;
}

div.pattern {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #d4d4d4;
  background-image: url(pattern.svg);
  background-size: 450px 450px;
  animation: bgmove 8s infinite linear;
}

section.scratchedout {
  mix-blend-mode:...

JavaScript

const canvasIn = document.querySelector("canvas.in")
const canvasOut = document.querySelector("canvas.out")

const hoverTags = document.querySelectorAll(".hoverme")


const hoverInfo = document.querySelector(".hover-info")

let isMouseDown = false

//canvas
const setupCanvas = function (canvas) {
  const w = window.innerWidth
  const h = window.innerHeight
  const dpi = window.devicePixelRatio
  
  canvas.width = w * dpi
  canvas.height = h * dpi
  canvas.style.width = w + "px"
  canvas.style.height = h + "px"
  
  // 2d context
  const context = canvas.getContext("2d")
  context.scale(dpi, dpi)
  
  
  if (canvas.classList.contains("in")) {
    context.fillStyle = "#000000"
  	context.strokeStyle = "#ffffff"
  } else {
    context.fillStyle = "#ffffff"
	  context.strokeStyle = "#000000"
  }
  
  context.lineWidth = 80
  context.lineCap = "round"
  context.lineJoin = "round"
  
  context.shadowBlur = 10
  context.shadowColor = context.strokeStyle
    
  context.rect(0, 0, w, h)
  context.fill()
}

// draw, based on the canvas, x and y
const startDraw = function (canvas, x, y) {
  const context = canvas.getContext("2d")
  
//   const colors = ["red", "yellow", "blue", "green"]
//   const randomNum = Math.floor(Math.random() * colors.length)
  
//   context.strokeStyle = colors[randomNum]
  
  context.moveTo(x, y)
  context.beginPath()
}

// lets draw based on three things, canvas, x and y
const moveDraw = function (canvas, x, y) {
  const context = canvas.getContext("2d")
  
  if (isMouseDown) {
    context.lineTo(x, y)
  	context.stroke()
  }
  
}






setupCanvas(canvasIn)
setupCanvas(canvasOut)

document.addEventListener("mousedown", function (event) {
  isMouseDown = true
  startDraw(canvasIn, event.pageX, event.pageY)
  startDraw(canvasOut, event.pageX, event.pageY)
})

document.addEventListener("mouseup", function () {
  isMouseDown = false
})

document.addEventListener("touchstart", function (event) {
  isMouseDown = true
  startDraw(canvasIn, event.pageX,...