缩放元素与背景覆盖与jQuery成比例 [英] Scale element proportional to Background Cover with jQuery

查看:93
本文介绍了缩放元素与背景覆盖与jQuery成比例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个棘手的问题:
我有一个完整的背景在我正在工作的网站。
现在我想附加一个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({
' top':yPos +'%',
'margin-left':xPos +'%',
'width':xSize +'px',
'height':ySize + px'
});

});
}

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

我的想法是:
If(imageWidth / windowWidth)< 1然后设置Value为var Scale =(windowWidth / imageWidth)else var Scale(windowHeight / imageHeight)
并使用var Scale进行转换:scale(Scale,Scale)
但是我无法管理这项工作...



也许你们可以帮助我...

解决方案

background-size的解决方案:cover



我想给你解决方案(或者考虑作为一个想法)。您可以在此处查看工作演示。调整窗口大小以查看结果。



首先,我不明白为什么你使用 transform code> top: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 coordnates



snippet-code-css lang-css prettyprint-override> 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-position:center;}。hotspot {position:absolute; z-index:1; background:red;}

 < script src = ://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js>< / script>< div id ='image'>< / div>  



background-size的解决方案: p>

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

  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 coordnates



  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: :150,宽度:100},{x:900,y:550,高度:100,宽度:25} var aspectRatio = imageWidth / imageHeight; $(window).resize(function(){positionHotSpots();}); var positionHotSpots = function(){$('。hotspot')。remove(); var wi = 0,hi = 0; var r = $('#image')。width()/ $('#image')。 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 * hx)/ imageWidth; var y =(hi * hy)/ 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:包含;背景重复:无重复; background-position:center;}。hotspot {position:absolute; z-index:1; background:red;}  

 < script src = ://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% a href =https://jsbin.com/vifili/edit?html,css,js,output =nofollow>此处。调整窗口大小以查看结果。



这里我们不需要计算图像尺寸,因为图像总是适合div。因此,我们可以使用视口和实际图像的 height width 计算热点的新坐标。



  var imageWidth = 1920; var imageHeight = 1368; var hotspots = [{x:100,y:200,height:100,width:50},{x :x:900,y:550,高度:100,宽度:100},{x:600,y:600,高度:150, };; $(window).resize(function(){positionHotSpots();}); var positionHotSpots = function(){$('。hotspot')。 $ .each(hotspots,function(i,h){var x =($('#image')。width()* hx)/ imageWidth; var y =($('#image')。height hy)/ imageHeight; var ww =($('#image')。width()*(h.width))/ imageWidth; var hh =($('#image')。height ))/ imageHeight; var hotspot = $('< div>')。addClass('hotspot')。css({top:y,left:x,height:hh,width:ww}); ').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 = ://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js>< / script>< div id ='image'>< / div>  



Canvas解决方案 b

基于@JayMee的评论,创建与实际图像和 draw 画布



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

  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: :150,宽度:100},{x:900,y:550,高度:100,宽度: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-position:center;}  

 <!DOCTYPE html> ;< html>< head> < script src =https://code.jquery.com/jquery-2.1.4.js>< / script> < meta charset =utf-8> < meta name =viewportcontent =width = device-width> < title> JS Bin< / title>< / head>< body> < div id ='image'>< / div>< / body>< / html>  

>

I have a tricky question: I have a fullsize background over the site I'm working on. Now I want to attach a div to a certain position on the image and also that the div scales in the same way the my background image with the "background-size: cover" property does. So in this example, I have a picture of a city, which covers the browser window and I want my div to overlay one particular building, no matter of the window size.

I already managed to make the div sticking to one position, but cant make it resize properly. What I did so far:

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);

My idea was: If (imageWidth / windowWidth) < 1 then set Value for var Scale = (windowWidth / imageWidth) else var Scale ( windowHeight / imageHeight ) and to use the var Scale for transform: scale (Scale,Scale) but I couldnt manage to make this work…

Maybe you guys could help me out…

解决方案

Solution for background-size:cover

I am trying to give you solution(or consider as an idea). You can check working demo here. Resize the window to see the result.

First,I didn't understand why you are using transform,top:50% and left:50%for hotspot. So I tried to solve this using minimal use-case and adjusted your markup and css for my convenience.

Here rImage is the aspect ratio of the original image.

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

In window resize handler,calculate the aspect ration of viewport r. Next,the trick is to find the dimensions of the image when we resize the window. But,viewport will clip the image to maintain aspect ratio. So to calculate the image dimensions we need some formula.

When using background-size:cover to calculate the dimensions of image,below formulas are used.

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

And

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

You can refer this URL for more understanding on image dimensions calculation when using background-size:cover.

After getting the dimensions of the image, we need to plot the hot-spot coordinates from actual image to new image dimensions.

To fit the image in viewport image will be clipped on top & bottom / left & right of the image. So we should consider this clipped image size as an offset while plotting hotspots.

offset_top=(image_height-viewport_height)/2
offset_left=(image_width-viewport_width)/2

add this offset values to each hotspot's x,y coordnates

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>

Solution for background-size:contain

When using background-size:contain to calculate the dimensions of image, below formulas are used.

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

And

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

To fit the image in viewport additional space will be added on top & bottom / left & right of the image. So we should consider this space as an offset while plotting hotspots.

offset_top=(viewport_height-image_height)/2
offset_left=(viewport_width-image_width)/2

Add this offset values to each hotspot's x,y coordnates

 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>

Solution for background-size:100% 100%

This is the solution if someone looking for background-size:100% 100% check the working demo here. Resize the window to see the result.

Here we don't need to calculate the image dimensions as the image will always fit to into the div. So we can just calculate the new coordinates of hotspot using height and width of viewport and actualimage.

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>

Canvas solution

Based on comment by @JayMee , create a canvas with same dimensions as actual image and draw hotspots as rectangles on the canvas.

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>

这篇关于缩放元素与背景覆盖与jQuery成比例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆