Skip to content Skip to sidebar Skip to footer

Zoom On An Image On Mouse Move: Reaching All Corners

I'm working on a zoom functionality. This zoom is a fixed box with 100% of the window size and inside an image with the 200% of the width of the fixed box. This zoom needs to work

Solution 1:

You were really close. You just need to calculate for image.height - window.height when getting vertical percentage.

This will also work with different image aspect ratios, since it takes image height into account when making calculations. Width is a non-issue since it is always double the window width.

var Zoom = function(imageZoom) {
  this.urlImage = imageZoom;
  this.img = undefined;
  this.$img = undefined;

  this.init = function() {
    this.loaders("on");
    this.calcs();
  };
  this.calcs = function() {
    var self = this;
    this.img = new Image();
    this.img.onload = function() {
      self.build();
    };
    this.img.src = this.urlImage;
  };
  this.loaders = function(status) {
    switch (status) {
      case "on":
        $('#loader').fadeIn(200);
        break;
      case "off":
        $('#loader').fadeOut(200);
        break;
    }
  };
  this.build = function() {
    var self = this;
    this.$img = $(self.img);

    $('#zoom').fadeIn(200).append(this.$img);

    this.$img.on('mousedown', function(e) {
      e.preventDefault();
    });

    // this is the problematic function
    $('body').on('mousemove', function(e) {
      e.preventDefault();

      var wx = $(window).width();
      var wy = $(window).height();
      var iy = self.$img.height();

      var px = e.pageX;
      var py = e.pageY;

      var tx = -1 * (px / wx) * wx;
      var ty = -1 * (py / wy) * (iy - wy);

      self.$img.css({
        'transform': 'translate(' + tx + 'px, ' + ty + 'px)'
      });
    });
    self.loaders("off");
  };
};

var zoom = new Zoom("http://dummyimage.com/2000x1200/000/fff");
zoom.init();
#zoom {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1000000;
  display: none;
}
#zoom img {
  width: 200%;
  height: 100%;
  height: auto;
  position: absolute;
  cursor: crosshair;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
body {
  margin: 0;
}
* {
  box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="loader">Loading</div>
<div id="zoom"></div>

As a bonus:

If you want to get rid of the empty space left when aspect ratio of the image is high (jsfiddle), you can make sure the image height is at least equal to window height (jsfiddle). But, you will need to set width: auto in this case, so image will not always be twice as wide as window.


Solution 2:

I think you can achieve what you want with CSS modification. If you try to use clip, transform translate and transform scale together in onmousemove event, you can shift the image as specified in your question. Please let me know, if this is desired behavior, thank you.

var divPos = {left:0,top:0};
var offset = $("#loader").offset();
$(document).mousemove(function(e){
  divPos = {
    left: e.pageX - offset.left,
    top: e.pageY - offset.top
  };

  console.log("x:" + divPos.left + " y: " + divPos.top);
});

var Zoom = function(imageZoom) {
  this.urlImage = imageZoom;
  this.img = undefined;
  this.$img = undefined;

  this.init = function() {
    this.loaders("on");
    this.calcs();
  };
  
  this.calcs = function() {
    var self = this;
    this.img = new Image();
    this.img.onload = function() {
      self.build();
    };
  
    this.img.src = this.urlImage;
  };
  this.loaders = function(status) {
    switch(status) {
      case "on":
        $('#loader').fadeIn(200);
        break;
      case "off":
        $('#loader').fadeOut(200);
        break;
    }
  };
  this.build = function() {
    var self = this;
    this.$img = $(self.img);
                
    $('#zoom').fadeIn(200).append(this.$img);
                
    this.$img.on('mousedown', function(e) {
      e.preventDefault();
    });

                
    // this is the problematic function
    $('body').on('mousemove', function(e) {
      e.preventDefault();

      var width = $(self.img).width();
      var height = $(self.img).height();
      // img center calculation
      var imgCenterX = width/2;
      var imgCenterY = height/2;
      // translate calculation
      var tx = imgCenterX-divPos.left;
      var ty = imgCenterY-divPos.top;

      // clip calculation
      var c0 = divPos.top/2;
      var c1 = divPos.left/2 + width/2;
      var c2 = divPos.top/2 + height/2;
      var c3 = divPos.left/2;

      console.log(c0 + ',' + c1 + ',' + c2 + ',' + c3);

      var t = 'translate('+ tx +'px, '+ ty +'px)';
      var c = 'rect('+ c0 +'px,'+ c1 +'px,'+ c2 +'px,'+ c3 +'px)';
      self.$img.css({'transform': t + ' scale(2,2)'});
      self.$img.css({'clip': c});
    });
    self.loaders("off");
  };
};

var zoom = new Zoom("http://dummyimage.com/2000x1230/000/fff");
zoom.init();
#zoom {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 1000000;
            display: none;
}
#zoom img {
            width: 100%;
            height: 100%;
            position: absolute;
            cursor: crosshair;
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            -khtml-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="loader">Loading</div>
<div id="zoom"></div>

Post a Comment for "Zoom On An Image On Mouse Move: Reaching All Corners"