我有一张(国家的)图片,就像一张地图。在此图像上,我放置了城市标记。我需要放大/缩小图像,但将标记放在同一位置。
我正在缩放图像:
var $map = $('#map-img'),
$mapW = $map.width(),
$mapH = $map.height();
$(document).on('click', '.zoom', function(e){
e.preventDefault();
var $this = $(this),
type,
scale = 1,
scale_factor = 0.125,
//css transform map
$map.css({
'-moz-transform': 'scale(' + scale + ')',
'-webkit-transform': 'scale(' + scale + ')',
'-o-transform': 'scale(' + scale + ')',
'-ms-transform': 'scale(' + scale + ')',
'transform': 'scale(' + scale + ')'
});
// recalculate width and height of map
$map_data = $map[0].getBoundingClientRect();
var $mH = $map_data.height;
var $mW = $map_data.width;
$('.point').each(function(k, obj){
var $this = $(this);
// calculate top / left position from element css without 'px'
var $top_px = ($this.css('top').replace(/[^-\d\.]/g, '') / $mapH) * 100;
var $left_px = ($this.css('left').replace(/[^-\d\.]/g, '') / $mapW) *100;
$this.css({
'top' : $top_px +'%',
'left' : $left_px +'%'
});
});
});
当前,当我单击缩放时,地图图像会缩放,但标记会停留在同一位置。
我要实现的目标:单击“缩放”按钮(无论单击“放大”还是“缩小”都没有关系),我要缩放图像并将标记移动到其新的计算位置,与Google地图相同。
有人可以指出一个主意吗? 谢谢
更新1
现在我要像这样重新计算$ mapH,$ mapW(我已经在上面编辑了我的代码):
$map_data = $map[0].getBoundingClientRect();
var $mH = $map_data.height;
var $mW = $map_data.width;
这是因为应用变换时,元素的实际宽度和高度不会更改,因此我使用getBoundingClientRect()来获取变换后的宽度/高度。
我的问题是,在缩放图像时,我也想移动标记,这就是我被卡住的原因。
更新2
我使用的比率是0.125,如果我将其乘以标记的顶部/左侧位置,标记将始终从顶部-左至右-底部对角移动,这不是理想的结果。
相反,我想同时且均匀地将它们从初始标记位置移动到各个方向(上,右,下,左)的缩放位置。
答案 0 :(得分:0)
您好hellheim,欢迎来到Stack Overflow!
您在加载时设置了$mapH
和$mapW
变量,但此后再也不要更改。根据地图的缩放大小,需要在按钮单击例程中重新计算这些内容。最简单的方法就是将声明移到事件处理程序中:
$(document).on('click', '.zoom', function(e){
e.preventDefault();
//css transform map
$map.css({
'-moz-transform': 'scale(' + scale + ')',
'-webkit-transform': 'scale(' + scale + ')',
'-o-transform': 'scale(' + scale + ')',
'-ms-transform': 'scale(' + scale + ')',
'transform': 'scale(' + scale + ')'
});
var $map = $('#map-img'),
$mapW = $map.width(),
$mapH = $map.height();
$('.point').each(function(k, obj){
var $this = $(this);
// calculate top / left position from element css without 'px'
var $top_px = ($this.css('top').replace(/[^-\d\.]/g, '') / $mapH) * 100;
var $left_px = ($this.css('left').replace(/[^-\d\.]/g, '') / $mapW) *100;
$this.css({
'top' : $top_px +'%',
'left' : $left_px +'%'
});
});
});
更新1
CSS transform
是一个非常有用的功能,但是在我最新的Codepen中,我遇到了一个问题,即缩放图像的位置不符合我的期望,因此我改为更改它以改变图像的宽度和高度。
这是我如何实现缩放的基本摘要:
缩放时:
在代码中,这将是:
HTML
<input type="button" class="zoom" data-factor="0.75" value="Zoom out [-]" />
<input type="button" class="zoom" data-factor="1.25" value="Zoom in [+]" />
<input type="button" class="zoom" data-factor="reset" value="Reset" />
JS
var $map= null,
originalWidth = baseWidth = 0,
originalHeight = baseHeight = 0;
$().ready(function() {
$map = $("#map-img"),
originalWidth = baseWidth = $map.width(),
originalHeight = baseHeight = $map.height();
});
$(".zoom").on("click", function() {
var $this = $(this);
var scaleFactor= $this.data("factor");
// in case a numeric value is present, zoom accordingly.
if (!isNaN(scaleFactor)) {
var newWidth = baseWidth * scaleFactor;
var newHeight = baseHeight * scaleFactor;
} else {
// reset to original size.
var newWidth = originalWidth;
var newHeight = originalHeight;
// calculate the scale factor to re-position the markers.
scaleFactor= originalWidth / baseWidth;
}
baseWidth= newWidth;
baseHeight= newHeight;
//css transform map
$map.css({
width: newWidth + "px",
height: newHeight + "px"
});
$(".point").each(function(k, obj) {
var $object = $(obj);
// calculate top / left position from element css without 'px'
var topPx = $object.css("top").replace(/[^-\d\.]/g, "") * scaleFactor;
var leftPx = $object.css("left").replace(/[^-\d\.]/g, "") * scaleFactor;
$object.css({
top: topPx + "px",
left: leftPx + "px"
});
});
});
关于您以前的代码的一些评论:
event.preventDefault
$map = $("#map-img");
可以,$mapW = $map.width()
可能会误导scale
和type
,因为我的代码示例不需要它们。如上所述,这是显示上述代码的Codepen。
更新2
那是一个很好的练习!如果要使用transform
,则需要首先找到图像的垂直和水平中心。然后,在缩放时,您需要根据到图像中心的偏移量计算新位置,然后将缩放因子应用于该位置。在下一次缩放时,根据上一次和当前的缩放来计算X和Y位置,一切就好。
相关代码
这部分代码是在加载图片后立即计算的:
HTML
<img src="https://mapchart.net/img/world-divided-population-map.png"
id="map-img" onload="calculateDimensions()"/>
JS
var $map = null,
previousZoom = 1;
var horizontalCenter, verticalCenter;
function calculateDimensions() {
$map = $("#map-img");
horizontalCenter = $map[0].width / 2;
verticalCenter = $map[0].height / 2;
$("#center")
.css("left", horizontalCenter + "px")
.css("top", verticalCenter + "px");
}
缩放时,我们需要根据元素相对于中心的位置应用正确的垂直和水平偏移量
$(".zoom").on("click", function() {
var $this = $(this);
var scaleFactor = $this.data("factor");
$map.css({
"-moz-transform": "scale(" + scaleFactor + ")",
"-webkit-transform": "scale(" + scaleFactor + ")",
"-o-transform": "scale(" + scaleFactor + ")",
"-ms-transform": "scale(" + scaleFactor + ")",
transform: "scale(" + scaleFactor + ")"
});
// calculate the change rate in reference to the last zoom.
var changeRatio = scaleFactor / previousZoom;
previousZoom = scaleFactor;
$(".point").each(function(k, obj) {
var $object = $(obj);
// calculate new top / left position
var newX =
($object[0].offsetLeft - horizontalCenter) * changeRatio +
horizontalCenter;
var newY =
($object[0].offsetTop - verticalCenter) * changeRatio + verticalCenter;
$object.css("left", newX + "px");
$object.css("top", newY + "px");
});
});
$("#center")
仅用于测试目的。如演示中所示,它可以简单地突出显示图像的中心。
这是更新的Codepen。