Javascript(jQuery)将图像缩放到其容器的中心点

Chr*_*ian 9 javascript math jquery scaling offset

这看起来应该很简单,但由于某种原因,我不能完全围绕它.我在"viewport"div中有一个图像,其中overflow属性设置为hidden.

我已经使用jQuery UI实现了简单的缩放和平移,但是我无法使缩放看起来来自视口的中心.我在Photoshop上做了一个小小的截屏视频我想要重现的效果:http://dl.dropbox.com/u/107346/share/reference-point-zoom.mov

在PS中,您可以调整缩放参考点,对象将从该点开始缩放.显然这对HTML/CSS/JS来说是不可能的,所以我试图找到合适的左边和顶部CSS值来​​模仿效果.

这是有问题的代码,删除了一些不必要的位:

HTML

<div id="viewport">
    <img id="map" src="http://dl.dropbox.com/u/107346/share/fake-map.png" alt="" />
</div>

<div id="zoom-control"></div>
Run Code Online (Sandbox Code Playgroud)

JavaScript的

$('#zoom-control').slider({
    min: 300,
    max: 1020,
    value: 300,
    step: 24,
    slide: function(event, ui) {
        var old_width = $('#map').width();
        var new_width = ui.value;
        var width_change = new_width - old_width;
        $('#map').css({
            width: new_width,

            // this is where I'm stuck...
            // dividing by 2 makes the map zoom
            // from the center, but if I've panned
            // the map to a different location I'd
            // like that reference point to change.
            // So instead of zooming relative to
            // the map image center point, it would
            // appear to zoom relative to the center
            // of the viewport. 
            left: "-=" + (width_change / 2),
            top: "-=" + (width_change / 2)
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

这是关于JSFiddle的项目:http://jsfiddle.net/christiannaths/W4seR/

Rob*_*b W 5

这是工作解决方案.我将在下一次编辑中解释逻辑.

功能逻辑:

  • 摘要:相对而言,请记住图像的中心位置.
    宽度和高度的计算是类似的,我只会解释height计算
    .详细解释只是函数逻辑的一个例子.可以在答案的底部找到具有不同变量名称的真实代码.

    1. 计算的中心(X,Y) #map,相对于#viewport.这可以通过使用来完成offset(),height()width()方法.

      // Absolute difference between the top border of #map and #viewport
      var differenceY = viewport.offset().top - map.offset().top;
      // We want to get the center position, so add it.
      var centerPosition = differenceY + viewport.height() * 0.5;
      // Don't forget about the border (3px per CSS)
      centerPosition += 3;
      // Calculate the relative center position of #map
      var relativeCenterY = centerPosition / map.height();
      // RESULT: A relative offset. When initialized, the center of #map is at
      //  the center of #viewport, so 50% (= 0.5)
      // Same method for relativeCenterX
      
      Run Code Online (Sandbox Code Playgroud)
    2. 计算新的顶部和左侧偏移量:

      // Calculate the effect of zooming (example: zoom 1->2 = 2)
      var relativeChange = new_width / old_width;
      // Calculate the new height
      var new_height = relativeChange * old_height;
      // Calculate the `top` and `left` CSS properties.
      // These must be negative if the upperleft corner is outside he viewport
      // Add 50% of the #viewport's height to correctly position #map
      //   (otherwise, the center will be at the upperleft corner)
      var newTopCss = -relativeCenterY * new_height + 0.5 * viewport.height();
      
      Run Code Online (Sandbox Code Playgroud)
    3. 更改CSS属性

      map.css("top", newTopCss);
      
      Run Code Online (Sandbox Code Playgroud)

演示:http://jsfiddle.net/W4seR/12/

var map = $('#map');
var viewport = $('#viewport');
// Cache the size of the viewport (300x300)
var viewport_size = {
    x: viewport.width(),
    y: viewport.height()
};

map.draggable();

$('#zoom-control').slider({
    min: 300,
    max: 1020,
    value: 300,
    step: 24,
    create: function() {
        map.css({
            'width': 300,
            'left': 0,
            'top': 0
        });
    },
    slide: function(event, ui) {
        var old_width = map.width();
        var old_height = map.height();
        var viewport_offset = viewport.offset();
        var offset = map.offset();
        offset = {
            top: viewport_offset.top - offset.top + .5*viewport_size.y +3,
            left: viewport_offset.left - offset.left + .5*viewport_size.x +3
        };
        // Relative offsets, relative to the center!
        offset.top = offset.top / old_height;
        offset.left = offset.left / old_width;

        var new_width = ui.value;
        var relative = new_width / old_width;
        var new_height = relative * old_height;

        offset = {
            top: -offset.top * new_height + .5*viewport_size.y,
            left: -offset.left * new_width + .5*viewport_size.x
        };

        var css_properties = {
            width: new_width,
            left: offset.left,
            top: offset.top
        };

        map.css(css_properties);

        trace((map.position().left));
    }
});
Run Code Online (Sandbox Code Playgroud)


RSG*_*RSG 1

我一直依赖陌生人的善意。相关变更:

// Calculate the offset as a percentage, accounting for the height of the window
var x_offset = ((map.position().left-150))/(old_width/2);
var y_offset = ((map.position().top-150))/(old_width/2);

var css_properties = {
    width: new_width,
    // Set the offset based on the existing percentage rather than 1/2
    // then readjust for the height of the window
    left: (new_width * x_offset /2 ) + 150 + "px", 
    top: (new_width * y_offset /2 ) + 150 + "px"
};
Run Code Online (Sandbox Code Playgroud)

如有必要,将硬编码替换150为视口实例化时设置的变量。