【问题标题】:Scale element proportional to Background Cover with jQuery使用 jQuery 与背景覆盖成比例的缩放元素
【发布时间】:2019-08-21 22:32:33
【问题描述】:

我有一个棘手的问题: 我在我正在处理的网站上有一个完整的背景。 现在我想将一个 div 附加到图像上的某个位置,并且该 div 的缩放方式与具有“背景大小:封面”属性的背景图像相同。 所以在这个例子中,我有一张城市的图片,它覆盖了浏览器窗口,我希望我的 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)

也许你们可以帮帮我……

【问题讨论】:

  • 这是一个问得很好的问题。
  • 我的想法:如果 (imageWidth / windowWidth)
  • 这是一个有趣的问题,如果您没有得到任何好的答案,请告诉我,我会提供bounty 以使其更具吸引力。
  • 这可能听起来很傻,但你不能把它们“混合”成一张图片吗? div中到底有什么?如果你在画布上渲染它,你可以让整个东西调整大小和保持比率等。
  • @LGSon...大声笑,我一直使用 vw,vh 单位,当然还有后备。我怎么会错过......这是一个很棒的线程)

标签: javascript jquery html css screen-resolution


【解决方案1】:

background-size:cover 的解决方案

我正在尝试为您提供解决方案(或作为一个想法考虑)。您可以查看工作演示here。调整窗口大小以查看结果。

首先,我不明白您为什么使用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时,您可以参考this URL了解更多关于图像尺寸计算的知识。

得到图像的尺寸后,我们需要绘制从实际图像到新图像尺寸的热点坐标。

为了使图像适合视口,图像将被剪裁在图像的顶部和底部/左侧和右侧。所以我们应该在绘制热点时将这个剪裁的图像大小视为偏移量。

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>

background-size: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>

解决背景尺寸:100% 100%

如果有人正在寻找 background-size:100% 100%,请查看工作演示 here,这就是解决方案。调整窗口大小以查看结果。

这里我们不需要计算图像尺寸,因为图像总是适合 div。所以我们可以使用viewport和actualimage的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 的评论,在画布上创建一个与实际图像相同尺寸的canvasrectangles 热点。

这种方法的一个优点是我们不必在调整窗口大小时重新计算热点坐标,因为热点是在图像本身中绘制的。

 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 位置?
  • 在脚本开头的图像尺寸旁边。var h = { x: CUSTOMX, y: CUSTOMY, height: 100, width: 50};
  • 如果您可以合并 2 个答案并从 background-size 值中读出它是否具有 cover100%,我会很高兴。一个以background-size: contain; 为目标的版本也会很有趣。只要有可能,我将奖励bounty,以获得完全符合要求的答案。
  • 另外,如果var h = { x: imageWidth / 2, y: imageHeight / 2, height: 100, width: 50 }; 可以是一个热点数组将会非常有趣。
  • @LGSon 合并了答案,为background-size:contains 和热点数组实现
【解决方案2】:

好的,所以没有多少人知道 CSS 单元 vhvw(意思是 ViewportHeight 和 ViewportWidth)。我创建了一个在页面加载时运行一次的脚本(不像其他一些在每次调整大小时运行的答案)。

计算背景图片的比例,给overlayContainer添加两条CSS规则,就完成了。

里面还有一个div#square,目的是我们有一个比例为1:1的容器作为画布。此比例可确保在您制作叠加元素时,垂直和水平百分比距离相同。

对于background-size: cover,请参阅this Fiddle

对于background-size: contain,请参阅this 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 only 解决方案,虽然它在这里,隐藏在这个答案中,因此我决定将它添加到同一个中。

通过将这两行添加到#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 添加解决方案?
  • 还请解释额外的square div 的用途(我在没有的情况下进行了测试并看到了 id 的作用,但最好在答案中包含它)
  • 我在答案中添加了background-size: contain的选项,现在解释#square的用途
  • 非常感谢...而且您不需要 2 个不同的计算脚本,它们返回相同的结果,在最大/最小宽度之间切换就可以了。
  • 很棒的纯 CSS 解决方案!非常感谢!好东西!
【解决方案3】:

好的,所以我尝试使用您最初的想法,并在这里和那里只修改了一些。

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

$(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

堆栈sn-p

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/(您可以非常有效地使用预览窗口。请注意,可以调整代码以采用基于像素的尺寸和热点定位,您只需要在计算时考虑容器和图像大小刻度值)

    更新:background-size: contain 行为使用相同的计算,除非 containerRatio 小于 比 bgRatio。 Updating the background css and flipping the sign around is enough.

    【讨论】:

    • 如此简单而高效。你刚刚有资格获得第二次赏金。如果您可以帮助我提供基于像素的版本和background-size: contain(带有百分比/像素)的版本,您就明白了。
    • 如果您有可能帮助我完成上述请求,请告诉我。 ..和我+1,我之前玩过它,它看起来坚如磐石,没有滞后:)
    • @LGSon:感谢您的评论 :) 我会用contain 版本更新答案
    • @o.v.很好的例子,但是为什么你在.hot-spot 上使用content:"";z-index:1; 这有点奇怪......??
    • @RokoC.Buljan:你说得对,那是从原始 codepen 懒惰地复制的 :)
    【解决方案5】:

    下面是一个 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>

    【讨论】:

    • 谢谢,请用工作代码 sn-p 更新它,我会给你一个 +1
    • 感谢LGSon,如果您有任何问题,请告诉我!
    • 我有一个,您的示例中的热点似乎不起作用?
    • 现在我可以看到它,但它不动
    • 还是不动……我用的是最新的Chrome
    【解决方案6】:

    解决问题的更简单/更好的方法是使用 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/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-04
      • 2016-07-24
      • 2012-12-19
      • 2016-06-23
      • 1970-01-01
      相关资源
      最近更新 更多