放大鼠标滚轮点(使用比例和平移)

dar*_*i0h 11 javascript html5 image zoom

这个问题类似于这个问题:放大一个点(使用缩放和平移) 或者甚至是这个:图像缩放以鼠标位置为中心 但我不想在画布上做它而是正常图像(或者更确切地说是图像的容器div).所以缩放应该像谷歌地图一样.我实际上是黑客/增强iDangerous Swiper zoom(http://idangero.us/swiper/),这是我的出发点,这就是我到目前为止所做的:https: //jsfiddle.net/xta2ccdt/3 /

仅使用鼠标滚轮进行缩放.第一次放大时它可以完美地缩放,但我无法弄清楚如何在第一次放大后计算每个缩放.

这是我的代码: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');
  });


});
Run Code Online (Sandbox Code Playgroud)

HTML:

<div id="slideContainer">
  <div id="slide">
    <img src="http://content.worldcarfans.co/2008/6/medium/9080606.002.1M.jpg"></img>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

CSS:

#slideContainer{
  width:500px;
  height:500px;
  overflow:hidden;
}
#slide{
  width:100%;
  height:100%;
}
img{
  width:auto;
  height:auto;
  max-width:100%;
}
Run Code Online (Sandbox Code Playgroud)

我还想知道如果我从当前的那些中减去之前的translateX和translateY值,我可以根据需要放大相同的点,它会完美缩放,但是如果我放大一个点然后改变鼠标位置和缩放再次,它将不再按照预期进行缩放.示例:https://jsfiddle.net/xta2ccdt/4/

如果我改变鼠标位置,并计算旧鼠标位置和新鼠标位置之间的X和Y差异,并将其添加到差异计算中,它将第二次正确缩放.但第三次看起来差异仍然从总计算中减去,这将导致翻译再次移动图像,之后如果我们将鼠标放在相同的位置,它将再次正确缩放.所以我想我每次计算新的"差异"时都会添加旧鼠标位置和新鼠标位置之间的差异,这种作用,不再像我停止添加鼠标位置差异那样跳跃,但它仍然没有放大相同的位置,每次新的缩放都会使图像移动(偏移)一小部分.我认为这是因为每次都有一个新的缩放值,但是偏移不是线性的,它每次都接近于零,我无法弄清楚如何抵消偏移.以下是新示例:https://jsfiddle.net/xta2ccdt/5/示例中的 新图片:旧图片不再可用:https://jsfiddle.net/xta2ccdt/14/

Man*_*tto 12

您接近它,但最好分别存储x,y和比例并根据这些值计算变换.它使事情变得更容易+节省资源(不需要一遍又一遍地查找dom属性),

我把代码放到了一个很好的模块中:

function ScrollZoom(container,max_scale,factor){
    var target = container.children().first()
    var size = {w:target.width(),h:target.height()}
    var pos = {x:0,y:0}
    var zoom_target = {x:0,y:0}
    var zoom_point = {x:0,y:0}
    var scale = 1
    target.css('transform-origin','0 0')
    target.on("mousewheel DOMMouseScroll",scrolled)

    function scrolled(e){
        var offset = container.offset()
        zoom_point.x = e.pageX - offset.left
        zoom_point.y = e.pageY - offset.top

        e.preventDefault();
        var delta = e.delta || e.originalEvent.wheelDelta;
        if (delta === undefined) {
          //we are on firefox
          delta = e.originalEvent.detail;
        }
        delta = Math.max(-1,Math.min(1,delta)) // cap the delta to [-1,1] for cross browser consistency

        // determine the point on where the slide is zoomed in
        zoom_target.x = (zoom_point.x - pos.x)/scale
        zoom_target.y = (zoom_point.y - pos.y)/scale

        // apply zoom
        scale += delta*factor * scale
        scale = Math.max(1,Math.min(max_scale,scale))

        // calculate x and y based on zoom
        pos.x = -zoom_target.x * scale + zoom_point.x
        pos.y = -zoom_target.y * scale + zoom_point.y


        // Make sure the slide stays in its container area when zooming out
        if(pos.x>0)
            pos.x = 0
        if(pos.x+size.w*scale<size.w)
            pos.x = -size.w*(scale-1)
        if(pos.y>0)
            pos.y = 0
         if(pos.y+size.h*scale<size.h)
            pos.y = -size.h*(scale-1)

        update()
    }

    function update(){
        target.css('transform','translate('+(pos.x)+'px,'+(pos.y)+'px) scale('+scale+','+scale+')')
    }
}
Run Code Online (Sandbox Code Playgroud)

通过电话使用它

new ScrollZoom($('#container'),4,0.5)
Run Code Online (Sandbox Code Playgroud)

参数是:

  1. container:要缩放的元素的包装器.该脚本将查找容器的第一个子节点并将变换应用于它.
  2. max_scale:最大比例(4 = 400%缩放)
  3. factor:变焦速度(1 =每个鼠标滚轮刻度+ 100%变焦)

JSFiddle在这里

  • @Jsilvermist 确定,布雷。https://jsfiddle.net/f9kctwby/ 。公平地说,它实际上是 `size.w*(scale-1)/2`,我的错。 (2认同)