JSFiddle - React, Tailwind, and code Playground

by John Doe

JavaScript

/* initialize stuff */

var cvs = document.createElement('canvas')
cvs.width = 500
cvs.height = 300
var ctx = cvs.getContext('2d')

ctx.fillStyle = '#afa'
ctx.fillRect(0, 0, cvs.width, cvs.height)

document.body.appendChild(cvs)
cvs.clear()

var mouseDownAngle = null
var angleDiff = 0
var angle = 0

function sliderule(sign = 1, offset = 0) {
  var endPoint = (angle, length, radius) => [
    cvs.width / 2 + Math.cos(angle + offset) * (radius + length * sign),
    cvs.height / 2 + Math.sin(angle + offset) * (radius + length * sign)
  ]
  var base = 10
  var maxExp = 5
  var absMax = 1e3
  var upperLimit = Math.min(Math.pow(base, maxExp), absMax)
  var upperLimitAngle = 2 * Math.PI * Math.min(maxExp, Math.log(absMax) / Math.log(base))
  var flength = l => 50.0 * (maxExp * 1.1 - l) / maxExp //40 / (l + 1)
  var radius = cvs.height / 3
  //
  if (sign < 0) {
    ctx.beginPath()
    ctx.fillStyle = '#faa'
    ctx.arc(cvs.width / 2, cvs.height / 2, radius, 0, Math.PI * 2)
    ctx.fill()
  }
  // ticks
  ctx.fillStyle = '#000'
  for (var k = 1; k < upperLimit; k++) {
    if (k % base != 0) {
      //console.log('drawing ' + k)
      var log = Math.log(k) / Math.log(base)
      var length = flength(log)
      var angle = log * 2 * Math.PI
      ctx.lineWidth = 3 / Math.sqrt(k)
      // cvs.tick(angle, length, radius, width)
      ctx.beginPath()
      ctx.moveTo(...endPoint(angle, 0, radius))
      ctx.lineTo(...endPoint(angle, length, radius))
      ctx.stroke()
    }
  }
  // spiral
  var dphi = 0.02
  ctx.fillStyle = '#000'
  ctx.lineWidth = 1
  ctx.beginPath()
  var log = 0
  var length = flength(log)
  ctx.moveTo(...endPoint(0, length, radius))
  for (var phi = 0; phi <= upperLimitAngle; phi += dphi) {
    log = phi / 2 / Math.PI
    length = flength(log)
    ctx.lineTo(...endPoint(phi, length, radius))
  }
  ctx.stroke()
}
sliderule()
sliderule(-1, 0)