缩放图像和标记

时间:2019-06-11 11:34:12

标签: javascript css

我有一张(国家的)图片,就像一张地图。在此图像上,我放置了城市标记。我需要放大/缩小图像,但将标记放在同一位置。

我正在缩放图像:

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,如果我将其乘以标记的顶部/左侧位置,标记将始终从顶部-左至右-底部对角移动,这不是理想的结果。

相反,我想同时且均匀地将它们从初始标记位置移动到各个方向(上,右,下,左)的缩放位置。

1 个答案:

答案 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中,我遇到了一个问题,即缩放图像的位置不符合我的期望,因此我改为更改它以改变图像的宽度和高度。

这是我如何实现缩放的基本摘要:

  1. 存储图像的原始高度和宽度,以便以后重新设置

缩放时:

  1. 根据缩放系数更改图像的宽度和高度
  2. 根据缩放系数更改所有标记的位置

在代码中,这将是:

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
  • 如果变量表示jQuery对象,我建议在变量前加上“ $”。 $map = $("#map-img");可以,$mapW = $map.width()可能会误导
  • 不要创建不需要的变量或方法,因为它们只会使您的代码膨胀。我从声明中删除了scaletype,因为我的代码示例不需要它们。

如上所述,这是显示上述代码的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