HTML5 canvas full degree image rotation

by casamia743

HTML

<!-- Click run button if image is not shown -->

<div id="control">
  <input id="slider" type="range" min="0" max="360" value="0"/>
  <button id="descButton">-</button>
  <button id="incButton">+</button>
  <span>step</span>
  <input id="step" value="10"/>
  <span>current: <span id="currentDegree">0</span></span>
</div>


<div id="result">

</div>

CSS

canvas {
  border: 1px solid red;
}

#result {
  border: 1px solid blue;
  padding:0;
  margin: 0;
}

img {
  margin: 0;
}

input#step {
  width: 30px;
}

div#control {
  padding: 10px;
}

JavaScript

/**
* MENIFESTO:
* name: HTML5 canvas full degree image rotation
* author: casamia743@gmail.com
* writtenAt : 9.8.2019
* stackoverflow: https://stackoverflow.com/a/57417439/4678741
* 
* NOTE: 
* essential part of this rotation code are
* (function) calcProjectedRectSizeOfRotatedRect
* (function) getRotatedImage
* (value) app.boundaryRad
*
* All other codes are assistants for this example app.
*/

// NOTE: If beach image image is not shown, click run button, refresh browser, or change source image url

// NOTE: to print console log, set DEBUG=true
const DEBUG = true;

const app = {degree: 0, step: 10, boundaryRad: 0};

function init() {
  const image = new Image();
  image.src = "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" // horizontal image
  //image.src = "https://i.imgur.com/1q5O8sy.jpg"; // vertical image
  image.crossOrigin = "Anonymous";
  image.onload = function() {
    const boundaryRad = Math.atan(image.width / image.height);
    app.boundaryRad = boundaryRad;
    debug('boundrary rad', boundaryRad, 'degree', boundaryRad * 180 / Math.PI);
    render();
  };
  
  app.image = image;
      
  document.getElementById('slider').addEventListener('change', (e) => {
    const degree = parseInt(e.target.value);
    app.degree = degree;
    updateComponentValue();
    render();
  })
  
  document.getElementById('incButton').addEventListener('click', e => {
    app.degree = (360 + app.degree + app.step) % 360;
    updateComponentValue();
    render();
  })
  
  document.getElementById('descButton').addEventListener('click', e => {
    app.degree = (360 + app.degree - app.step) % 360;
    updateComponentValue();
    render();
  })
  
  document.getElementById('step').addEventListener('change', e => {
    const step = parseInt(e.target.value);
    debug('step', step);
    app.step = step;
  })
  
  function updateComponentValue() {
    document.getElementById('slider').value = app.degree;
   ...