Javascript: Zoom to the cursor point on scroll

Viewed 388

I am having an image which can get Zoomed in and out on scroll, with some specific conditions. Now, What is happening is that on zooming in, the scroll is setting to top.

What I need is the image to bee zoomed to the cursor position. I have used the scrollTo() function, but it doesn't seem to be working.

Here is the piece of code that I have tried

var mainDiv = document.getElementById('mainDiv');

// Zoom On Scroll
var image = document.getElementById('cephImage');
image.onload = createImage();

var actualImageWidth;
var actualImageHeight;

function createImage() {
  actualImageWidth = image.width;
  actualImageHeight = image.height;
  console.log("Actual Image Width and Height: ", [actualImageWidth, actualImageHeight]);
}

var zoomScrollX;
var zoomScrollY;

var zoomFactor = 1;
image.addEventListener('wheel', function(event) {
  xPos = event.pageX - $('#cephImage').offset().left;
  yPos = event.pageY - $('#cephImage').offset().top;

  if (event.deltaY < 0) {
    if (zoomFactor <= 4) {
      console.log('zoomFactor Value : ', zoomFactor);
      zoomFactor += 1;
      console.log('Zoom Factor: ', zoomFactor);


      console.log("(Zoom ScrollX, Zoom ScrollY)", [zoomScrollX, zoomScrollY]);

      checkZoom();

      image.scrollTo(zoomScrollX, zoomScrollY);

    } else {
      console.log('Reached Max Zoom Level');
    }

  } else {
    if (zoomFactor >= 2) {
      console.log('zoomFactor Value: ', zoomFactor);
      zoomFactor -= 1;
      console.log('Zoom Factor: ', zoomFactor);
      console.log('Zoom out...')

      zoomScrollX = xPos * zoomFactor;
      zoomScrollY = yPos * zoomFactor;

      checkZoom();


      image.scrollTo(zoomScrollX, zoomScrollY);

    } else {
      console.log('Reached Minimum Zoom Level');
    }
  }
});


// Function CheckZoom Level.
function checkZoom() {
  console.log('Zoom Level: ', zoomFactor);
  // console.log('[x,y]: ', [xPos,yPos]);
  console.log("actual Image Width: ", actualImageWidth);
  console.log("actual Image Height: ", actualImageHeight);

  var imageWidth = actualImageWidth * zoomFactor;
  var imageHeight = actualImageHeight * zoomFactor;

  image.width = imageWidth;
  image.height = imageHeight;

  console.log('image Width: ', image.width);
  console.log('Image Height: ', image.height);
  console.log('New Image Width and Height: ', [imageWidth, imageHeight]);
}

// Pan Function 
const Pannable = (EL) => {

  const initial = {
    x: 0,
    y: 0
  };
  let isPan = false;

  const getXY = ({
    clientX,
    clientY
  }) => {
    const bcr = EL.getBoundingClientRect();
    return {
      x: clientX - bcr.left,
      y: clientY - bcr.top,
    }
  };

  const panStart = (ev) => {
    ev.preventDefault();
    isPan = true;
    const {
      x,
      y
    } = getXY(ev);
    initial.x = EL.scrollLeft + x;
    initial.y = EL.scrollTop + y;
  };

  const panMove = (ev) => {
    if (!isPan) return; // Do nothing
    const {
      x,
      y
    } = getXY(ev);
    EL.scrollTo(initial.x - x, initial.y - y);
  };

  const panEnd = (ev) => {
    isPan = false;
  };

  EL.addEventListener("mousedown", panStart);
  document.addEventListener("mousemove", panMove);
  document.addEventListener("mouseup", panEnd);
};

document.querySelectorAll(".viewport").forEach(Pannable);
.viewport {
  margin: 50px auto;
  width: 600px;
  height: 600px;
  overflow: auto;
  /* Set to hidden to remove scrollbars */
}

.viewport>* {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="mainDiv" class="mainDiv viewport" width="400" height="300">
  <img src="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_960_720.jpg" id="cephImage" class="cephImage" alt="Cephalogram">
</div>

The scrollTo() doesn't seem to work, What I am missing here ?.

UPDATE: The question is Edited . So here is the Fiddle related :- https://jsfiddle.net/georgoboy/hnmqae4o/

2 Answers

You need to add certain logic to implement this functionality, I have implemented it but it is closed source as of now I will create a GitHub repo for that and attach it to this answer till then you can refer to this

https://dev.to/stackfindover/zoom-image-point-with-mouse-wheel-11n3

let me know if you face any problem understanding any logic implemented here.

That's because image is not scrollable. You should use scrollTo for mainDiv, instead and that will work. Here is the fiddle.

Code:

var mainDiv = document.getElementById('mainDiv');

// Zoom On Scroll
var image = document.getElementById('cephImage');
image.onload  = createImage();

var actualImageWidth;
var actualImageHeight;

function createImage()
{
    actualImageWidth = image.width;
    actualImageHeight = image.height;
    console.log("Actual Image Width and Height: ", [actualImageWidth, actualImageHeight]);
}

var zoomScrollX;
var zoomScrollY;

var zoomFactor = 1;
image.addEventListener('wheel', function(event)
{
  xPos = event.pageX - $('#cephImage').offset().left;
  yPos = event.pageY - $('#cephImage').offset().top;
  
  if(event.deltaY < 0)
  { 
    if(zoomFactor <=4)
    {
      console.log('zoomFactor Value : ', zoomFactor);
      zoomFactor += 1; 
      console.log('Zoom Factor: ', zoomFactor); 
      

      console.log("(Zoom ScrollX, Zoom ScrollY)", [zoomScrollX,zoomScrollY]); 
    
      checkZoom();
      
      mainDiv.scrollTo(zoomScrollX, zoomScrollY);

    }

    else{
      console.log('Reached Max Zoom Level');
    }

  }

  else
  { 
    if(zoomFactor>=2)
    {
      console.log('zoomFactor Value: ', zoomFactor);
      zoomFactor -= 1;  
      console.log('Zoom Factor: ', zoomFactor);
      console.log('Zoom out...') 
      
      zoomScrollX = xPos * zoomFactor;
      zoomScrollY = yPos * zoomFactor;
       
      checkZoom(); 
      
      
      mainDiv.scrollTo(zoomScrollX, zoomScrollY);

    }
    else{
      console.log('Reached Minimum Zoom Level');
    }
  }
});


// Function CheckZoom Level.
function checkZoom()
{
    console.log('Zoom Level: ', zoomFactor);
    // console.log('[x,y]: ', [xPos,yPos]);
    console.log("actual Image Width: ", actualImageWidth);
    console.log("actual Image Height: ", actualImageHeight);

    var imageWidth  = actualImageWidth * zoomFactor;
    var imageHeight = actualImageHeight * zoomFactor;

    image.width = imageWidth;
    image.height = imageHeight;

    console.log('image Width: ', image.width);
    console.log('Image Height: ', image.height);
    console.log('New Image Width and Height: ', [imageWidth, imageHeight]); 
}

// Pan Function 
const Pannable = (EL) => {

const initial = {x: 0, y: 0};
let isPan = false;

const getXY = ({clientX, clientY}) => {
  const bcr = EL.getBoundingClientRect();
  return {
    x: clientX - bcr.left,
    y: clientY - bcr.top,
  }
}; 

const panStart = (ev) => {
  ev.preventDefault();
  isPan = true;
  const {x, y} = getXY(ev);
  initial.x = EL.scrollLeft + x;
  initial.y = EL.scrollTop + y;
};

const panMove = (ev) => {
  if (!isPan) return; // Do nothing
  const {x, y} = getXY(ev);
  EL.scrollTo(initial.x - x,  initial.y - y);
};

const panEnd = (ev) => {
  isPan = false;
};

EL.addEventListener("mousedown", panStart);
document.addEventListener("mousemove", panMove);
document.addEventListener("mouseup", panEnd);
};

document.querySelectorAll(".viewport").forEach(Pannable);
Related