这看起来应该很简单,但出于某种原因,我无法将自己的大脑包裹起来。我在"视口内有一个图像" div,其overflow属性设置为隐藏。
我已经使用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>
的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)
});
}
});
这是关于JSFiddle的项目:http://jsfiddle.net/christiannaths/W4seR/
答案 0 :(得分:5)
这是工作解决方案。我将在下一次编辑中解释逻辑。
功能逻辑:
摘要:请记住图像的中心位置,相对
宽度和高度的计算类似,我只解释height
计算。详细解释只是函数逻辑的一个例子。可以在答案的底部找到具有不同变量名称的真实代码。
计算#map
相对于#viewport
的中心(x,y)。这可以通过使用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
计算新的顶部和左侧偏移量:
// 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();
更改CSS属性
map.css("top", newTopCss);
演示: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));
}
});
答案 1 :(得分:1)
我一直依赖the kindness of strangers。相关变化:
// 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"
};
如果需要,用视口实例化设置的变量替换硬编码的150
。
答案 2 :(得分:0)
这是一个快速工作版本: http://jsfiddle.net/flabbyrabbit/chLkZ/
可能不是最好的解决方案,但似乎工作得很好,希望它有所帮助。
更新:对不起,这只适用于移动地图时缩放为0的情况。