JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
<img id="test" src="https://images.unsplash.com/photo-1624268450274-84f420bc9e70?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80">

CSS

#test {
  position: absolute;
  transform-origin: 0 0;
  transition: transform 330ms ease-in-out;
}

JavaScript

const img = document.getElementById("test");

let currentScale = 1;

let translateX = 0
let translateY = 0

const factor = 1

const zoom = (nextScale, event) => {
  const ratio = 1 - nextScale / currentScale

  const {
    clientX,
    clientY
  } = event

  translateX += (clientX - translateX) * ratio
  translateY += (clientY - translateY) * ratio

  img.style.transform = `translate(${translateX}px, ${translateY}px) scale(${nextScale})`

  currentScale = nextScale
}


const zoomDebounce = _.debounce(zoom, 30)

const onWheel = e => {
  e.preventDefault()
  const delta = e.deltaY / 5
  const nextScale = currentScale + delta * factor
  zoomDebounce(nextScale, e)
}

window.addEventListener('wheel', onWheel, {
  passive: false
})