This question is similar to this one: Zooming in (using scale and translation) or even this: Scaling an image to fit the position of the mouse but I don’t want to do this on the canvas, but a normal image (or rather, a div container). Therefore, scaling should be like Google maps. I actually hack / zoom iDangerous Swiper ( http://idangero.us/swiper/ ), and this is my starting point, and this is what I got so far: https://jsfiddle.net/xta2ccdt/3/
Enlarge only the mouse wheel. The first time you zoom in, it scales very well, but I can't figure out how to calculate each scale after the first.
Here is my code: JS:
$(document).ready(function(){ $("#slideContainer").on("mousewheel DOMMouseScroll", function (e) { e.preventDefault(); var delta = e.delta || e.originalEvent.wheelDelta; var zoomOut; if (delta === undefined) { //we are on firefox delta = e.originalEvent.detail; zoomOut = delta ? delta < 0 : e.originalEvent.deltaY > 0; zoomOut = !zoomOut; } else { zoomOut = delta ? delta < 0 : e.originalEvent.deltaY > 0; } var touchX = e.type === 'touchend' ? e.changedTouches[0].pageX : e.pageX; var touchY = e.type === 'touchend' ? e.changedTouches[0].pageY : e.pageY; var scale = 1, translateX, translateY; if(zoomOut){ //we are zooming out //not interested in this yet }else{ //we are zooming in scale = scale + 0.5; var dimensionMultiplier = scale - 0.5;//when image is scaled up offsetWidth/offsetHeight doesn't take this into account so we must multiply by scale to get the correct width/height var slideWidth = $("#slide")[0].offsetWidth * dimensionMultiplier; var slideHeight = $("#slide")[0].offsetHeight * dimensionMultiplier; var offsetX = $("#slide").offset().left;//distance from the left of the viewport to the slide var offsetY = $("#slide").offset().top;//distance from the top of the viewport to the slide var diffX = offsetX + slideWidth / 2 - touchX;//this is distance from the mouse to the center of the image var diffY = offsetY + slideHeight / 2 - touchY;//this is distance from the mouse to the center of the image //how much to translate by x and y so that poin on image is alway under the mouse //we must multiply by 0.5 because the difference between previous and current scale is always 0.5 translateX = ((diffX) * (0.5)); translateY = ((diffY) * (0.5)); } $("#slide").css("transform", 'translate3d(' + translateX + 'px, ' + translateY + 'px,0) scale(' + scale + ')').css('transition-duration', '300ms'); }); });
HTML:
<div id="slideContainer"> <div id="slide"> <img src="http://content.worldcarfans.co/2008/6/medium/9080606.002.1M.jpg"></img> </div> </div>
CSS
#slideContainer{ width:500px; height:500px; overflow:hidden; } #slide{ width:100%; height:100%; } img{ width:auto; height:auto; max-width:100%; }
I also realized that if you subtract the previous translateX and translateY values from the current ones, I can increase the same point as I want, and it will scale perfectly, but if I increase by one point, then change the mouse position and zoom in, it will no longer scale as intended. Example: https://jsfiddle.net/xta2ccdt/4/
If I change the position of the mouse and calculate the difference between X and Y between the old and the new position of the mouse and add this to the diffusion calculation, it will scale correctly the second time. But for the third time, it seems that this difference is still subtracted from the general calculation, and this will force the translation to move the image again, after which if we hold the mouse in the same position, it will scale correctly again. So I decided that I would just add the difference between the old and the new mouse position every time I calculate a new “diff”, and such works, there’s no longer a jump like it was when I stopped adding the difference in the mouse position, but it’s all still not scaled in the same position, with each new zoom it moves (shifts) the image by a small amount. I believe that this is due to the fact that each time a new scaling value appears, but the offset is not linear, it approaches zero less each time, and I cannot figure out how to compensate for the offset. Here is a new example: https://jsfiddle.net/xta2ccdt/5/ New image in the example: the old one is no longer available: https://jsfiddle.net/xta2ccdt/14/