Scale by wheel

by Andrey Izman

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="container">
  <div class="stage" id="image_box">
    <img id="image" src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
  </div>
  <div class="actions">
    <div class="action">
      <label for="rotate">Rotate </label>
      <input type="range" id="rotate" name="rotate" min="0" max="360">
      <button onclick="reset()">Reset All</button>
    </div>
  </div>
</div>

CSS

.container {
      background-color: lightgrey;
    }
    
    .stage {
      height: 90vh;
      width: 100%;
      overflow: hidden;
    }
    
    #image {
      transform-origin: 50% 50%;
      height: auto;
      width: 40%;
      cursor: grab;
    }
    
    .actions {
      display: flex;
      position: absolute;
      bottom: 0;
      left: 0;
      height: 1.5rem;
      width: 100%;
      background-color: lightgrey;
    }
    
    .action {
      margin-right: 1rem;
    }

JavaScript

const img = document.getElementById('image_box');
    const rotate = document.getElementById('rotate');
    let mouseX;
    let mouseY;
    let mouseTX;
    let mouseTY;
    let startXOffset = 222.6665;
    let startYOffset = 224.713;
    let startX = 0;
    let startY = 0;
    let panning = false;

    const ts = {
      scale: 1,
      rotate: 0,
      translate: {x: 0,y: 0}
    };

    img.onwheel = function(event) {
      event.preventDefault();
      //need more handling  to avoid fast scrolls
      var func = img.onwheel;
      img.onwheel = null;

      let rec = img.getBoundingClientRect();
      let x = (event.clientX - rec.x) / ts.scale;
      let y = (event.clientY - rec.y) / ts.scale;

      let delta = (event.wheelDelta ? event.wheelDelta : -event.deltaY);
      ts.scale = (delta > 0) ? (ts.scale + 0.2) : (ts.scale - 0.2);

      //let m = (ts.scale - 1) / 2;
      let m = (delta > 0) ? 0.1 : -0.1;
      ts.translate.x += (-x * m * 2) + (img.offsetWidth * m);
      ts.translate.y += (-y * m * 2) + (img.offsetHeight * m);

      setTransform();
      img.onwheel = func;
    };


    function setTransform() {
      const steps = `translate(${ts.translate.x}px,${ts.translate.y}px) scale(${ts.scale})`;
      //console.log(steps);
      img.style.transform = steps;
    }

    function reset() {
      ts.scale = 1;
      ts.rotate = 0;
      ts.translate = {
        x: 0,
        y: 0
      };
      rotate.value = 180;
      img.style.transform = 'none';
    }

    setTransform();