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 like this:
- When the cursor is in the center of the window, the image should be in the center.
- When the cursor is in the top right corner, the image should stay at the top right corner of the window (so reach the image with the corner)
- When the cursor is in the middle bottom corner, the image should center horizontally and reach the total bottom, so we can see the middle bottom part of the image.
- And so on.
I make an approachment, but I can't reach the corners perfectly. This is my snippet (see the comments in onmousemove function):
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();
// calc the percents of the window where
var px = 100 * e.pageX / $(window).width();
var py = 100 * e.pageY / $(window).height();
// calc of the percent pixel of the image
var fx = self.$img.width() * px / 100;
var fy = self.$img.height() * py / 100;
// render it left / 2 and top / 1.5 (the 1.5 value is imaginary!!)
self.$img.css({'transform': 'translate('+ -(fx/2) +'px, '+ -(fy/1.5)+'px)'});
});
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: 200%;
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;
}
<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>
The problem is that I put the fx/1.5
because fx/2
doesn't work. But the horizontal value works perfecly.
What value can I config to reach all corners? Why the left value (division of the pixels by 2) works perfectly when the top value doesn't?
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.
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>
来源:https://stackoverflow.com/questions/38703966/zoom-on-an-image-on-mouse-move-reaching-all-corners