首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用jQuery缩放与背景覆盖成比例的元素

使用jQuery缩放与背景覆盖成比例的元素
EN

Stack Overflow用户
提问于 2016-03-11 21:52:17
回答 6查看 3.6K关注 0票数 27

我有一个棘手的问题:我对我正在工作的网站有一个完整的背景。现在,我希望将div附加到图像上的某个位置,并且该div的缩放方式与我的背景图像的“background size: cover”属性的缩放方式相同。所以在这个例子中,我有一个城市的图片,它覆盖了浏览器窗口,我希望我的div覆盖在一个特定的建筑上,而不管窗口的大小。

我已经设法使div粘贴到一个位置,但不能正确地调整它的大小。到目前为止,我所做的:

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

代码语言:javascript
复制
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,那么设置变量Scale的值= (windowWidth / imageWidth),否则设置变量Scale ( windowHeight / imageHeight ),并使用var Scale进行转换: scale (Scale,Scale),但我无法在…中执行此操作

也许你们能帮帮我…

EN

回答 6

Stack Overflow用户

发布于 2016-03-12 04:41:17

用于背景的解决方案-大小:cover

我正在试着给你一个解决方案(或考虑作为一个想法)。您可以查看正在运行的演示here。调整窗口大小以查看结果。

首先,我不明白你为什么要用transformtop:50%left:50%来做热点。所以我试着用最少的用例来解决这个问题,并且为了我的方便调整了你的标记和css。

这里rImage是原始图像的纵横比。

代码语言:javascript
复制
 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计算图像的尺寸时,使用以下公式。

代码语言:javascript
复制
if(actual_image_aspectratio <= viewport_aspectratio)
    image_width = width_of_viewport
    image_height = width_ofviewport / actual_image_aspectratio 

代码语言:javascript
复制
if(actual_image_aspectratio > viewport_aspectratio)
    image_width = height_of_viewport * actual_image_aspectratio 
    image_height = height_of_viewport

在使用background-size:cover时,您可以参考this URL了解更多关于镜像尺寸计算的内容。

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

为了适合视口中的图像,图像将被裁剪到图像的顶部和底部/左侧和右侧。因此,在绘制热点时,我们应该将此裁剪图像大小作为偏移量。

代码语言:javascript
复制
offset_top=(image_height-viewport_height)/2
offset_left=(image_width-viewport_width)/2

将此偏移值添加到每个热点的x,y坐标中

代码语言:javascript
复制
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();
代码语言:javascript
复制
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;
}
代码语言:javascript
复制
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='image'></div>

背景大小的解决方案:包含

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

代码语言:javascript
复制
if(actual_image_aspectratio <= viewport_aspectratio)
    image_width = height_of_viewport * actual_image_aspectratio 
    image_height = height_of_viewport

代码语言:javascript
复制
if(actual_image_aspectratio > viewport_aspectratio)
    image_width = width_of_viewport
    image_height = width_ofviewport / actual_image_aspectratio

为了使图像适合视口,将在图像的顶部和底部/左侧和右侧添加额外的空间。因此,在绘制热点时,应将此空间视为偏移量。

代码语言:javascript
复制
offset_top=(viewport_height-image_height)/2
offset_left=(viewport_width-image_width)/2

将此偏移值添加到每个热点的x,y坐标中

代码语言:javascript
复制
 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();
代码语言:javascript
复制
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;
}
代码语言:javascript
复制
<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。因此,我们可以使用视口和实际图像的heightwidth来计算新的热点坐标。

代码语言:javascript
复制
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();
代码语言:javascript
复制
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;
}
代码语言:javascript
复制
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='image'></div>

Canvas解决方案

基于@JayMee的评论,在画布上创建一个尺寸与实际图像相同的canvas和与rectangles相同的draw热点。

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

代码语言:javascript
复制
 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();
代码语言:javascript
复制
html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}
#image {
  height: 100%;
  width: 100%;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
}
代码语言:javascript
复制
<!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>

票数 12
EN

Stack Overflow用户

发布于 2016-03-19 11:16:42

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

它计算背景图像的比例,将两个CSS规则添加到overlayContainer中,然后就完成了。

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

有关background-size: cover,请参阅this Fiddle

有关background-size: contain,请参阅this Fiddle

HTML:

代码语言:javascript
复制
<div id="overlayContainer">
  <div id="square">
    <!-- Overlaying elements here -->
  </div>
</div>

CSS:

代码语言:javascript
复制
#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):

代码语言:javascript
复制
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'})

希望这能有所帮助

由更新

我没想到会找到一个只有CSS的解决方案,尽管它就在这里,隐藏在这个答案中,因此我决定将它添加到相同的解决方案中。

通过将这两行添加到#overlayContainer规则(适用于covercontain),就可以删除该脚本。

代码语言:javascript
复制
width:  calc(100vh * (1920 / 1368));
height: calc(100vw * (1368 / 1920));

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

使用background-size: cover的示例

代码语言:javascript
复制
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%;
}
代码语言:javascript
复制
<div id="overlayContainer">
  <div id="square">
    <div></div>
  </div>
</div>

票数 9
EN

Stack Overflow用户

发布于 2016-03-14 10:07:55

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

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

代码语言:javascript
复制
$(this).css({
  'margin-top': yPos + 'px',
  'margin-left': xPos + 'px',
  'width': xSize + 'px',
  'height': ySize + 'px'
});

然后,我们要做的就是检查视口的比例,看看我们必须如何修改div的属性

代码语言:javascript
复制
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

堆栈代码段

代码语言:javascript
复制
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);
代码语言:javascript
复制
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: "";
}
代码语言:javascript
复制
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container"></div>

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35942014

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档