使用jQuery按比例缩放元素以适应背景覆盖

28

我有一个棘手的问题: 我的网站上有一个全尺寸背景。 现在,我想将一个div附加到图像的某个位置,并且使该div与具有“background-size:cover”属性的背景图像以相同的方式缩放。 所以在这个例子中,我有一张覆盖浏览器窗口的城市图片,我希望我的div覆盖其中的一个特定建筑物,而不管窗口大小如何。

我已经成功地将div固定到一个位置,但无法正确调整其大小。到目前为止,我做了什么:

http://codepen.io/EmmieBln/pen/YqWaYZ

var imageWidth = 1920,
    imageHeight = 1368,
    imageAspectRatio = imageWidth / imageHeight,
    $window = $(window);

var hotSpots = [{
    'x': -160,
    'y': -20,
    'height': 400,
    'width': 300
}];

function appendHotSpots() {
    for (var i = 0; i < hotSpots.length; i++) {
        var $hotSpot = $('<div>').addClass('hot-spot');
        $('.container').append($hotSpot);
    }
    positionHotSpots();
}

function positionHotSpots() {
    var windowWidth = $window.width(),
        windowHeight = $window.height(),
        windowAspectRatio = windowWidth / windowHeight,
        $hotSpot = $('.hot-spot');

    $hotSpot.each(function(index) {
        var xPos = hotSpots[index]['x'],
            yPos = hotSpots[index]['y'],
            xSize = hotSpots[index]['width'],
            ySize = hotSpots[index]['height'],
            desiredLeft = 0,
            desiredTop = 0;

        if (windowAspectRatio > imageAspectRatio) {
            yPos = (yPos / imageHeight) * 100;
            xPos = (xPos / imageWidth) * 100;
            xSize = (xSize / imageWidth) * 1000;
            ySize = (ySize / imageHeight) * 1000;
        } else {
            yPos = ((yPos / (windowAspectRatio / imageAspectRatio)) / imageHeight) * 100;
            xPos = ((xPos / (windowAspectRatio / imageAspectRatio)) / imageWidth) * 100;
        }

        $(this).css({
            'margin-top': yPos + '%',
            'margin-left': xPos + '%',
            'width': xSize + 'px',
            'height': ySize + 'px'
        });

    });
}

appendHotSpots();
$(window).resize(positionHotSpots);

我的想法是: 如果(imageWidth / windowWidth)< 1,则设置var Scale的值为(windowWidth / imageWidth),否则var Scale = (windowHeight / imageHeight) 然后使用var Scale进行变换:scale(Scale,Scale) 但是我无法使其正常工作...

也许你们可以帮我解决这个问题...


这是一个非常好的问题。 - user1017882
2
这是一个有趣的问题,如果你没有得到任何好的答案,请告诉我,我会提供一个赏金来增加它的吸引力。 - Asons
@JᴀʏMᴇᴇ 想象一下它是地图上的针脚,或者房间图纸上的家具,所有这些都是动态添加的...然后它就有意义了,至少对我来说是这样。 - Asons
@MaximilianBecker,我可以问一下您是否对所给答案感到满意吗? - Asons
1
@LGSon... 哈哈,我经常使用vw、vh单位,当然也有备选方案。我怎么可能会错过这个.... 这是一个很棒的讨论串) - tnt-rox
显示剩余8条评论
6个回答

13

解决background-size:cover的问题

我尝试给您提供一个解决方案(或者说是想法)。您可以在这里检查工作演示。调整窗口大小以查看结果。

首先,我不明白为什么您要使用transformtop:50%left:50%来设置热点。因此,我尝试使用最小的用例并调整您的标记和CSS以方便我自己来解决这个问题。

这里的rImage是原始图像的宽高比。

 var imageWidth = 1920;
 var imageHeight = 1368;
 var h = {
   x: imageWidth / 2,
   y: imageHeight / 2,
   height: 100,
   width: 50
 };
 var rImage= imageWidth / imageHeight;

在窗口大小调整处理程序中,计算视口的纵横比r。 接下来的诀窍是找到当我们调整窗口大小时图像的尺寸。但是,视口将剪裁图像以保持其纵横比。因此,为了计算图像尺寸,我们需要一些公式。
使用background-size:cover计算图像尺寸时,使用以下公式。
if(actual_image_aspectratio <= viewport_aspectratio)
    image_width = width_of_viewport
    image_height = width_ofviewport / actual_image_aspectratio 

并且
if(actual_image_aspectratio > viewport_aspectratio)
    image_width = height_of_viewport * actual_image_aspectratio 
    image_height = height_of_viewport

您可以参考此链接,了解使用background-size:cover时图像尺寸计算的更多信息。
在获取图像的尺寸后,我们需要将热点坐标从实际图像绘制到新图像尺寸上。
为了使图像适应视口,图像将被裁剪在顶部和底部/左侧和右侧。因此,在绘制热点时,我们应该考虑这个裁剪图像大小作为偏移量。
offset_top=(image_height-viewport_height)/2
offset_left=(image_width-viewport_width)/2

将这些偏移值添加到每个热点的x,y坐标上

var imageWidth = 1920;
var imageHeight = 1368;
var hotspots = [{
  x: 100,
  y: 200,
  height: 100,
  width: 50
}, {
  x: 300,
  y: 500,
  height: 200,
  width: 100
}, {
  x: 600,
  y: 600,
  height: 150,
  width: 100
}, {
  x: 900,
  y: 550,
  height: 100,
  width: 25
}];
var aspectRatio = imageWidth / imageHeight;

$(window).resize(function() {
  positionHotSpots();
});
var positionHotSpots = function() {
  $('.hotspot').remove();
  var wi = 0,
    hi = 0;
  var r = $('#image').width() / $('#image').height();
  if (aspectRatio <= r) {
    wi = $('#image').width();
    hi = $('#image').width() / aspectRatio;
  } else {
    wi = $('#image').height() * aspectRatio;
    hi = $('#image').height();
  }
  var offsetTop = (hi - $('#image').height()) / 2;
  var offsetLeft = (wi - $('#image').width()) / 2;
  $.each(hotspots, function(i, h) {

    var x = (wi * h.x) / imageWidth;
    var y = (hi * h.y) / imageHeight;

    var ww = (wi * (h.width)) / imageWidth;
    var hh = (hi * (h.height)) / imageHeight;

    var hotspot = $('<div>').addClass('hotspot').css({
      top: y - offsetTop,
      left: x - offsetLeft,
      height: hh,
      width: ww
    });
    $('body').append(hotspot);
  });
};
positionHotSpots();
html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}
#image {
  height: 100%;
  width: 100%;
  background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Alexanderplatz_Stadtmodell_1.jpg/1920px-Alexanderplatz_Stadtmodell_1.jpg');
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
}
.hotspot {
  position: absolute;
  z-index: 1;
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='image'></div>

背景大小为contain的解决方案

当使用background-size:contain计算图像尺寸时,将使用以下公式。

if(actual_image_aspectratio <= viewport_aspectratio)
    image_width = height_of_viewport * actual_image_aspectratio 
    image_height = height_of_viewport

同时

if(actual_image_aspectratio > viewport_aspectratio)
    image_width = width_of_viewport
    image_height = width_ofviewport / actual_image_aspectratio

为了适应视口,将在图像的顶部和底部/左侧和右侧添加额外的空间。因此,在绘制热点时,我们应该将这个空间视为偏移量。
offset_top=(viewport_height-image_height)/2
offset_left=(viewport_width-image_width)/2

将这些偏移量添加到每个热点的 x,y 坐标上。

 var imageWidth = 1920;
 var imageHeight = 1368;
 var hotspots = [{
   x: 100,
   y: 200,
   height: 100,
   width: 50
 }, {
   x: 300,
   y: 500,
   height: 200,
   width: 100
 }, {
   x: 600,
   y: 600,
   height: 150,
   width: 100
 }, {
   x: 900,
   y: 550,
   height: 100,
   width: 25
 }];
 var aspectRatio = imageWidth / imageHeight;

 $(window).resize(function() {
   positionHotSpots();
 });
 var positionHotSpots = function() {
   $('.hotspot').remove();
   var wi = 0,
     hi = 0;

   var r = $('#image').width() / $('#image').height();
   if (aspectRatio <= r) {
     wi = $('#image').height() * aspectRatio;
     hi = $('#image').height();

   } else {
     wi = $('#image').width();
     hi = $('#image').width() / aspectRatio;
   }
   var offsetTop = ($('#image').height() - hi) / 2;
   var offsetLeft = ($('#image').width() - wi) / 2;
   $.each(hotspots, function(i, h) {

     var x = (wi * h.x) / imageWidth;
     var y = (hi * h.y) / imageHeight;

     var ww = (wi * (h.width)) / imageWidth;
     var hh = (hi * (h.height)) / imageHeight;

     var hotspot = $('<div>').addClass('hotspot').css({
       top: y + offsetTop,
       left: x + offsetLeft,
       height: hh,
       width: ww
     });
     $('body').append(hotspot);
   });
 };
 positionHotSpots();
html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}
#image {
  height: 100%;
  width: 100%;
  background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Alexanderplatz_Stadtmodell_1.jpg/1920px-Alexanderplatz_Stadtmodell_1.jpg');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}
.hotspot {
  position: absolute;
  z-index: 1;
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='image'></div>

解决background-size:100% 100%的问题

如果有人正在寻找解决background-size:100% 100%的方法,请查看此处的工作演示。调整窗口大小以查看结果。

在这里,我们不需要计算图像尺寸,因为图像将始终适合div中。因此,我们可以使用视口和实际图像的heightwidth来计算热点的新坐标。

var imageWidth = 1920;
var imageHeight = 1368;
var hotspots = [{
  x: 100,
  y: 200,
  height: 100,
  width: 50
}, {
  x: 300,
  y: 500,
  height: 200,
  width: 100
}, {
  x: 600,
  y: 600,
  height: 150,
  width: 100
}, {
  x: 900,
  y: 550,
  height: 100,
  width: 25
}];

$(window).resize(function() {
  positionHotSpots();
});


var positionHotSpots = function() {
  $('.hotspot').remove();

  $.each(hotspots, function(i, h) {
    var x = ($('#image').width() * h.x) / imageWidth;
    var y = ($('#image').height() * h.y) / imageHeight;

    var ww = ($('#image').width() * (h.width)) / imageWidth;
    var hh = ($('#image').height() * (h.height)) / imageHeight;
    var hotspot = $('<div>').addClass('hotspot').css({
      top: y,
      left: x,
      height: hh,
      width: ww
    });
    $('body').append(hotspot);
  });

};
positionHotSpots();
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
#image {
  height: 100%;
  width: 100%;
  background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Alexanderplatz_Stadtmodell_1.jpg/1920px-Alexanderplatz_Stadtmodell_1.jpg');
  background-size: 100% 100%;
}
.hotspot {
  position: absolute;
  z-index: 1;
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='image'></div>

画布解决方案

根据@JayMee的评论,创建一个与实际图像具有相同尺寸的canvas,并在画布上将热点用rectangles绘制。

One advantage in this approach is we don't have to recalculate the hotspot coordinates on resizing window as the hotspot are drawn in image itself.

 var imageWidth = 1920;
 var imageHeight = 1368;
 var hotspots = [{
   x: 100,
   y: 200,
   height: 100,
   width: 50
 }, {
   x: 300,
   y: 500,
   height: 200,
   width: 100
 }, {
   x: 600,
   y: 600,
   height: 150,
   width: 100
 }, {
   x: 900,
   y: 550,
   height: 100,
   width: 25
 }];

 var positionHotSpots = function() {


   var canvas = document.createElement('canvas');
   canvas.height = imageHeight;
   canvas.width = imageWidth;
   var context = canvas.getContext('2d');
   var imageObj = new Image();
   imageObj.onload = function() {

     context.drawImage(imageObj, 0, 0);

     $.each(hotspots, function(i, h) {
       context.rect(h.x, h.y, h.width, h.height);
     });
     context.fillStyle = "red";
     context.fill();
     $('#image').css('background-image', 'url("' + canvas.toDataURL() + '")');
   };
   imageObj.setAttribute('crossOrigin', 'anonymous');
   imageObj.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Alexanderplatz_Stadtmodell_1.jpg/1920px-Alexanderplatz_Stadtmodell_1.jpg';

 };
 positionHotSpots();
html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}
#image {
  height: 100%;
  width: 100%;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
}
<!DOCTYPE html>
<html>

<head>
  <script src="https://code.jquery.com/jquery-2.1.4.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

<body>
  <div id='image'></div>
</body>

</html>


我该在哪里设置答案的自定义x/y位置? - Asons
在脚本开始时,紧接着图片尺寸的位置添加以下代码:var h = { x: CUSTOMX, y: CUSTOMY, height: 100, width: 50 }; - Pavan Teja
如果您能合并这两个答案,并从background-size的值中读取是否具有cover100%,我会很高兴。另外,针对background-size:contain;的版本也很有趣。一旦可以开始,我将授予bounty,以获得完全实现此功能的答案。 - Asons
如果 var h = { x: imageWidth / 2, y: imageHeight / 2, height: 100, width: 50 }; 可以是一个热点数组,那将非常有趣。 - Asons
@LGSon合并了答案,实现了background-size:contains和热点数组。 - Pavan Teja

10

好的,不是很多人知道CSS单位vhvw(即ViewportHeight和ViewportWidth)。我创建了一个脚本,在页面加载时运行一次(与其他一些答案不同,它们在每次调整大小时运行)。

它计算出背景图像的比率,向overlayContainer添加两个CSS规则,然后完成。

还有一个

#square
,其目的是我们拥有一个1:1比率的容器作为画布。此比率确保在制作覆盖元素时,垂直和水平百分比距离相同。

有关background-size:cover,请参见此Fiddle

有关background-size:contain,请参见此Fiddle

HTML:

<div id="overlayContainer">
  <div id="square">
    <!-- Overlaying elements here -->
  </div>
</div>

CSS样式表如下:
#overlayContainer{
  position: absolute; /* Fixed if the background-image is also fixed */
  min-width:  100vw; /* When cover is applied */
  min-height: 100vh; /* When cover is applied */
  max-width:  100vw; /* When contain is applied */
  max-height: 100vh; /* When contain is applied */
  top:  50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

#square{
  position: relative;
  padding-bottom: 100%;
}

/* When placing overlaying elements, make them all absolutely positioned, and work with percentages only */
/* Look at my Fiddles for examples */

JavaScript(jQuery):
var image = new Image()
image.src = $('body').css('background-image').replace(/url\((['"])?(.*?)\1\)/gi,'$2').split(',')[0]

/* When cover is applied, use this: */
$('#overlayContainer').css({'height':100/(image.width/image.height)+'vw','width':100/(image.height/image.width)+'vh'})

/* When contain is applied, use this: */
$('#overlayContainer').css({'height':100*(image.height/image.width)+'vw','width':100*(image.width/image.height)+'vh'})

希望这能帮到您。

@LGSon更新

我没想到会有一个仅使用CSS的解决方案,但确实在这个答案中隐藏着这个解决方案,因此我决定将其添加到同一位置。

通过将这两行添加到#overlayContainer规则中(适用于covercontain),可以放弃脚本。

width:  calc(100vh * (1920 / 1368));
height: calc(100vw * (1368 / 1920));

当然,脚本版本具有自动获取值的优点,但由于热点在背景中具有特定的位置点,因此图像大小很可能已知。

使用 background-size: cover 的示例

html, body {
  height: 100%;
  overflow: hidden;
}

body {
  margin: 0;
  background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Alexanderplatz_Stadtmodell_1.jpg/1920px-Alexanderplatz_Stadtmodell_1.jpg');
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
}

#overlayContainer {
  position: absolute;
  width:  calc(100vh * (1920 / 1368));
  height: calc(100vw * (1368 / 1920));
  min-width:  100vw;     /*  for cover    */
  min-height: 100vh;     /*  for cover    */
  /* max-width:  100vw;      for contain  */
  /* max-height: 100vh;      for contain  */
  top:  50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

#square {
  position: relative;
  padding-bottom: 100%;
}

#square div {
  position: absolute;
  top: 19.75%;
  left: 49.75%;
  width: 4.75%;
  height: 4.75%;
  background-color: rgba(255,0,0,.7);
  border-radius: 50%;
}
<div id="overlayContainer">
  <div id="square">
    <div></div>
  </div>
</div>


我印象深刻,到目前为止看起来真的很好,稍后会去尝试一下,谢谢,+1。你能否还提供一个background-size: contain的解决方案? - Asons
请解释一下额外的 square div 的目的(我测试了没有它的情况,但是在回答中有它会更好)。 - Asons
我认为这个编辑很好。你注意到计算值的方式没有任何区别,这是件好事! - Gust van de Wal
@LGSon:很高兴看到赏金种子对你有用,而且很棒地破解了仅使用CSS的方法!由于某些愚蠢的原因,我一直试图使用来自数据属性的图像尺寸……据我所知,这只是草案规范的一部分。:\ - Oleg
2
太棒了,纯CSS解决方案!非常感谢!太棒了! - Garavani
显示剩余7条评论

4

好的,我尝试使用您的原始想法,并仅在某些地方进行了微调。

我发现使用像素值比使用百分比更容易。所以:

$(this).css({
  'margin-top': yPos + 'px',
  'margin-left': xPos + 'px',
  'width': xSize + 'px',
  'height': ySize + 'px'
});

然后,我们只需要检查视口的比例,以确定如何修改 div 的属性。
if (windowAspectRatio > imageAspectRatio) {
  var ratio = windowWidth / imageWidth;
} else {
  var ratio = windowHeight / imageHeight;
}

xPos = xPos * ratio;
yPos = yPos * ratio;
xSize = xSize * ratio;
ySize = ySize * ratio;

工作示例:http://codepen.io/jaimerodas/pen/RaGQVm

堆栈片段

var imageWidth = 1920,
    imageHeight = 1368,
    imageAspectRatio = imageWidth / imageHeight,
    $window = $(window);

var hotSpots = [{
  x: -210,
  y: -150,
  height: 250,
  width: 120
}, {
  x: 240,
  y: 75,
  height: 85,
  width: 175
}];

function appendHotSpots() {
  for (var i = 0; i < hotSpots.length; i++) {
    var $hotSpot = $('<div>').addClass('hot-spot');
    $('.container').append($hotSpot);
  }
  positionHotSpots();
}



function positionHotSpots() {
  var windowWidth = $window.width(),
    windowHeight = $window.height(),
    windowAspectRatio = windowWidth / windowHeight,
    $hotSpot = $('.hot-spot');

  $hotSpot.each(function(index) {
    var cambio = 1,
        xPos = hotSpots[index]['x'],
        yPos = hotSpots[index]['y'],
        xSize = hotSpots[index]['width'],
        ySize = hotSpots[index]['height'],
        desiredLeft = 0,
        desiredTop = 0;
    
    if (windowAspectRatio > imageAspectRatio) {
      var ratio = windowWidth / imageWidth;
    } else {
      var ratio = windowHeight / imageHeight;
    }
    
    xPos = xPos * ratio;
    yPos = yPos * ratio;
    xSize = xSize * ratio;
    ySize = ySize * ratio;

    $(this).css({
      'margin-top': yPos + 'px',
      'margin-left': xPos + 'px',
      'width': xSize + 'px',
      'height': ySize + 'px'
    });

  });
}

appendHotSpots();
$(window).resize(positionHotSpots);
html, body {
  margin: 0;
  width: 100%;
  height: 100%;
}

.container {
  width: 100%;
  height: 100%;
  position: relative;
  background-image: url(https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Alexanderplatz_Stadtmodell_1.jpg/1920px-Alexanderplatz_Stadtmodell_1.jpg);
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
}

.hot-spot {
  background-color: red;
  border-radius: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  opacity: 0.8;
  content: "";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container"></div>


4
依靠css变换并将其应用于单个元素,无论热点数量如何,都能给您带来更好的性能(较少的DOM操作和更少的回流)。硬件加速也是一个不错的选择 :)
首先,元代码:
1. 在图像.container内创建.hot-spot--container。 2. 创建.hot-spot,并在.hot-spot--container内定位/调整大小。 3. 变换.hot-spot--container以模仿background-size: cover行为。 4. 每当有重新调整大小时重复步骤#3。
计算您的背景图像比例:
var bgHeight = 1368;
var bgWidth = 1920;
var bgRatio = bgHeight / bgWidth;

无论何时窗口大小改变,都重新计算容器比例:
var containerHeight = $container.height();
var containerWidth = $container.width();
var containerRatio = containerHeight / containerWidth;

计算比例因素以模仿background-size: cover的行为...

if (containerRatio > bgRatio) {
    //fgHeight = containerHeight
    //fgWidth = containerHeight / bgRatio
    xScale = (containerHeight / bgRatio) / containerWidth
} else {
    //fgHeight = containerWidth / bgRatio
    //fgWidth = containerWidth 
    yScale = (containerWidth * bgRatio) / containerHeight
}

将变换应用于热点容器元素,与背景图“同步”地重新调整大小和重新定位:

var transform = 'scale(' + xScale + ', ' + yScale + ')';

$hotSpotContainer.css({
    'transform': transform
});

Fiddled: https://jsfiddle.net/ovfiddle/a3pdLodm/(您可以很好地使用预览窗口进行操作。请注意,代码可以调整为以像素为基础的尺寸和热点定位,但在计算比例值时必须考虑容器和图像大小)

更新:当容器比率小于bgRatio时,background-size: contain行为使用相同的计算方式。更新背景css并翻转符号就足够了


1
如此简单,又高效。你刚刚为自己赢得了第二份赏金。如果你能帮我完成基于像素的版本和一个background-size: contain(包含百分比/像素)的版本,那么这份赏金就是你的了。 - Asons
请告诉我您是否有可能帮助我完成上述请求。另外,我给您点赞,因为我之前已经试用过它,表现非常稳定,没有任何延迟 :) - Asons
@LGSon:感谢您的评论 :) 我将使用“包含”版本更新答案。 - Oleg
@o.v. 很好的例子,但是为什么在.hot-spot上使用了content:"";z-index:1;呢?有点奇怪...?? - Roko C. Buljan
@RokoC.Buljan:你说得对,那是从原始的Codepen懒惰地复制过来的 :) - Oleg
开始了另一个悬赏,不过会等几天再分配它,看看是否有人能提出纯CSS的解决方案 :) - Asons

3
下面是一个jQuery解决方案,bgCoverTool插件根据父元素的背景图片的比例重新定位元素。
//bgCoverTool Properties
$('.hot-spot').bgCoverTool({
  parent: $('#container'),
  top: '100px',
  left: '100px',
  height: '100px',
  width: '100px'})

演示:

$(function() {
  $('.hot-spot').bgCoverTool();
});
html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}
#container {
  height: 100%;
  width: 100%;
  background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Alexanderplatz_Stadtmodell_1.jpg/1920px-Alexanderplatz_Stadtmodell_1.jpg');
  background-size: cover;
  background-repeat: no-repeat;
  position: relative;
}
.hot-spot {
  position: absolute;
  z-index: 1;
  background: red;
  left: 980px;
  top: 400px;
  height: 40px;
  width: 40px;
  opacity: 0.7;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>BG Cover Tool</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script type="text/javascript" charset="utf-8">
    //bgCoverTool jQuery plugin
    (function($) {
      $.bgCoverTool = function(element, options) {
        var $element = $(element),
          imgsize = {};
        var defaults = {
          parent: $element.parent(),
          top: $element.css('top'),
          left: $element.css('left'),
          height: $element.css('height'),
          width: $element.css('width')
        };
        var plugin = this;
        plugin.settings = {};
        plugin.init = function() {
          plugin.settings = $.extend({}, defaults, options);
          var tempurl = plugin.settings.parent.css('background-image').slice(4, -1)
          .replace('"', '').replace('"', '');
          var tempimg = new Image();
          var console = console || {
            error: function() {}
          };
          if (plugin.settings.parent.css('background-size') != "cover") {
            return false;
          }
          if (typeof tempurl !== "string") {
            return false;
          }
          if (plugin.settings.top == "auto" || plugin.settings.left == "auto") {
            console.error("#" + $element.attr('id') + " needs CSS values for 'top' and 'left'");
            return false;
          }
          $(tempimg).on('load', function() {
            imgsize.width = this.width;
            imgsize.height = this.height;
            imageSizeDetected(imgsize.width, imgsize.height);
          });
          $(window).on('resize', function() {
            if ('width' in imgsize && imgsize.width != 0) {
              imageSizeDetected(imgsize.width, imgsize.height);
            }
          });
          tempimg.src = tempurl;
        };
        var imageSizeDetected = function(w, h) {
          var scale_h = plugin.settings.parent.width() / w,
            scale_v = plugin.settings.parent.height() / h,
            scale = scale_h > scale_v ? scale_h : scale_v;
          $element.css({
            top: parseInt(plugin.settings.top, 10) * scale,
            left: parseInt(plugin.settings.left, 10) * scale,
            height: parseInt(plugin.settings.height, 10) * scale,
            width: parseInt(plugin.settings.width, 10) * scale
          });

        };
        plugin.init();
      };
      /**
       * @param {options} object Three optional properties are parent, top and left.
       */
      $.fn.bgCoverTool = function(options) {
        return this.each(function() {
          if (undefined == $(this).data('bgCoverTool')) {
            var plugin = new $.bgCoverTool(this, options);
            $(this).data('bgCoverTool', plugin);
          }
        });
      }
    })(jQuery);
  </script>
</head>

<body>
  <div id="container">
    <div class="hot-spot"></div>
  </div>
</body>

</html>


谢谢,如果您能提供一个工作的代码片段并更新它,我会给您加1分。 - Asons
谢谢LGSon,如果您有任何问题,请告诉我! - BendYourTaxes
我有一个问题,你的示例中的热点好像不起作用? - Asons
仍然没有移动...我正在使用最新的Chrome。 - Asons
那么在Firefox中也有一个问题,因为它在那里也无法工作,请花些时间确保在发布下一个更新之前它能够在主要浏览器中正常工作。 - Asons
显示剩余3条评论

3

一个更简单/更好的方法来解决您的问题是使用SVG元素,它更适合您的要求。SVG的好处是一切都会按比例缩放,默认情况下,因为它是矢量对象而不是文档流对象。

以下示例将演示该技术。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>SVG</title>
        <style type="text/css" media="screen">
            body {
                background: #eee;
                margin: 0;
            }
            svg {
                display: block;
                border: 1px solid #ccc;
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: #fff;
            }
            .face {
                stroke: #000;
                stroke-width: 20px;
                stroke-linecap: round
            }
        </style>
    </head>
    <body>
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="-350 -250 700 500">
            <circle r="200" class="face" fill="red"/>
            <path fill="none" class="face" transform="translate(-396,-230)" d="M487.41,282.411c-15.07,36.137-50.735,61.537-92.333,61.537 c-41.421,0-76.961-25.185-92.142-61.076"/>
            <circle id="leftEye" cx="-60" cy="-50" r="20" fill="#00F"/>
            <circle id="rightEye" cx="60" cy="-50" r="20" fill="#00F"/>
        </svg>
        <script type="text/javascript">
            document.getElementById('leftEye').addEventListener('mouseover', function (e) {
                alert('Left Eye');
            });
            document.getElementById('rightEye').addEventListener('mouseover', function (e) {
                alert('Right Eye');
            });
        </script>
    </body>
</html>

您可以添加图片到SVG中以实现您的需求。 https://jsfiddle.net/tnt1/3f23amue/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接