简体   繁体   English

使用jQuery与背景封面成比例的缩放元素

[英]Scale element proportional to Background Cover with jQuery

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. 现在我想将div附加到图像上的某个位置,并且div的缩放方式与使用“background-size:cover”属性的背景图像相同。 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. 所以在这个例子中,我有一个城市的图片,它覆盖了浏览器窗口,我希望我的div覆盖一个特定的建筑物,无论窗口大小。

I already managed to make the div sticking to one position, but cant make it resize properly. 我已经设法让div坚持一个位置,但不能让它适当调整大小。 What I did so far: 到目前为止我做了什么:

http://codepen.io/EmmieBln/pen/YqWaYZ 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… 我的想法是:如果(imageWidth / windowWidth)<1则设置值为var Scale =(windowWidth / imageWidth)否则var Scale(windowHeight / imageHeight)并使用var Scale进行变换:scale(Scale,Scale)但我不能设法使这项工作......

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. 首先,我不明白你为什么要使用transformtop:50%left:50%的热点。 So I tried to solve this using minimal use-case and adjusted your markup and css for my convenience. 因此,我尝试使用最少的用例来解决这个问题,并调整了你的标记和css以方便我。

Here rImage is the aspect ratio of the original image. 这里rImage是原始图像的纵横比。

 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 . 在窗口大小调整处理程序中,计算视口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. 当使用background-size:cover来计算图像的尺寸时,使用以下公式。

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 . 使用background-size:cover时,您可以参考此URL以更深入地了解图像尺寸计算。

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 将此偏移值添加到每个热点的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 * 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: 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. 当使用background-size:contain来计算图像的尺寸时,使用下面的公式。

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 将此偏移值添加到每个热点的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 * 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: 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% 背景尺寸解决方案:100%100%

This is the solution if someone looking for background-size:100% 100% check the working demo here . 如果有人寻找background-size:100% 100%这是解决方案background-size:100% 100%检查这里的工作演示。 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. 在这里,我们不需要计算图像尺寸,因为图像将始终适合div。 So we can just calculate the new coordinates of hotspot using height and width of viewport and 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() * hx) / imageWidth; var y = ($('#image').height() * hy) / 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. 根据@JayMee的评论,创建一个与实际图像尺寸相同的canvas ,并在画布上draw热点作为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(hx, hy, 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> 

Okay, so not a lot of people know about the CSS units vh and vw (meaning ViewportHeight and ViewportWidth). 好吧,所以很多人都不知道CSS单位vhvw (意思是ViewportHeight和ViewportWidth)。 I've created a script that runs one time at pageload (unlike some other answers that run at every resize ). 我创建了一个在pageload运行一次的脚本(与每次调整大小时运行的其他一些答案不同)。

It calculates the ratio of the background-image, adds two CSS rules to overlayContainer , and it's done. 它计算背景图像的比例,向overlayContainer添加两个CSS规则,并完成。

There's also a div #square in there, the purpose of which is that we have a container with a ratio of 1:1 as a canvas. 那里还有一个div #square ,其目的是我们有一个比例为1:1的容器作为画布。 This ratio ensures that when you're making the overlaying elements, vertical and horizontal percentual distances are the same. 此比率可确保在制作叠加元素时,垂直和水平百分比距离相同。

For background-size: cover , see this Fiddle . 对于background-size: cover ,请参阅此小提琴

For background-size: contain , see this Fiddle . 对于background-size: contain ,请参阅此小提琴

The HTML: HTML:

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

The CSS: 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 */

The JavaScript (jQuery): 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'})

Hope this helps 希望这可以帮助


Update by @LGSon @LGSon更新

I didn't expect to find a CSS only solution, though here it is, hiding itself in this answer, and therefore I decided to add it into the same. 我没想到会找到一个只有CSS的解决方案,虽然在这里,它隐藏在这个答案中,因此我决定将它添加到同一个中。

By adding these 2 lines to the #overlayContainer rule (works for both cover and contain ), the script can be dropped. 通过添加这两条线的#overlayContainer规则(同时适用于covercontain ),脚本可以被丢弃。

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

Of course the script version has the advantage of automatically get the values, though since the hotspot(s) has a specific location point in the background, the image size will most likely be known. 当然,脚本版本具有自动获取值的优点,但由于热点在背景中具有特定的位置点,因此图像大小很可能是已知的。

Sample with background-size: cover background-size: cover样本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> 

Ok, so I tried to use your original idea, and modified only a few bits here and there. 好的,所以我尝试使用你原来的想法,并在这里和那里只修改了几个位。

Instead of using percentages, I found it easier to use pixel values. 我没有使用百分比,而是发现使用像素值更容易。 So: 所以:

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

Then, all we have to do is check the proportion of the viewport to see how we have to modify the div 's properties 然后,我们要做的就是检查视口的比例,看看我们如何修改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;

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

Stack snippet 堆栈代码段

 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> 

Relying on css transforms and applying it to a single element gives you much better performance regardless of the number of hotspots (fewer DOM manipulations and much fewer re-flows). 依赖于css转换并将其应用于单个元素,无论热点数量多少(DOM操作更少,重新流动更少),都可以提供更好的性能。 Hardware acceleration is also a nice-to-have :) 硬件加速也是一个不错的选择:)

First, meta-code: 首先,元代码:

  1. Create a .hot-spot--container inside your image .container 在图像.container创建一个.hot-spot--container

  2. Create .hot-spot and position/size them within the .hot-spot--container .hot-spot--container创建.hot-spot并定位/调整它们的大小

  3. Transform .hot-spot--container mimicking background-size: cover behaviour 变换.hot-spot--container模仿background-size: cover行为

  4. Repeat #3 whenever there's a re-size 每当重新调整尺寸时重复#3

Calculate your bg image ratio: 计算你的bg图像比例:

var bgHeight = 1368;
var bgWidth = 1920;
var bgRatio = bgHeight / bgWidth;

Whenever the window is re-sized, re-calculate container ratio: 每当窗口重新调整大小时,重新计算容器比例:

var containerHeight = $container.height();
var containerWidth = $container.width();
var containerRatio = containerHeight / containerWidth;

Calculate scale factors to mimic background-size: cover behaviour... 计算比例因子以模拟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
}

...and apply the transform to the hot spot container element, essentially re-sizing and re-positioning it "in sync" with the background: ...并将变换应用于热点容器元素,基本上重新调整大小并将其与背景“同步”重新定位:

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

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

Fiddled: https://jsfiddle.net/ovfiddle/a3pdLodm/ (you can play with the preview window pretty effectively. Note the code can be adjusted to take pixel-based dimensions and positioning for hot spots, you'll just have to consider container and image sizes when calculating scale values) 摆弄: https ://jsfiddle.net/ovfiddle/a3pdLodm/(您可以非常有效地使用预览窗口。注意代码可以调整为基于像素的尺寸和定位热点,你只需要考虑计算比例值时的容器和图像大小)

Update: the background-size: contain behaviour uses the same calculation except when the containerRatio is smaller than the bgRatio. 更新: background-size: contain行为使用相同的计算,除非containerRatio 小于 bgRatio。 Updating the background css and flipping the sign around is enough . 更新背景css并翻转符号就足够了

Below is a jQuery solution,the bgCoverTool plugin repositions an element based on the scale of the parent's background image. 下面是一个jQuery解决方案,bgCoverTool插件根据父级背景图像的比例重新定位一个元素。

//bgCoverTool Properties
$('.hot-spot').bgCoverTool({
  parent: $('#container'),
  top: '100px',
  left: '100px',
  height: '100px',
  width: '100px'})

Demo: 演示:

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

A far simpler/better approach to you problem is to use an SVG element, it is better suited to your requirement. 解决问题的一个更简单/更好的方法是使用SVG元素,它更适合您的要求。 The cool thing about SVG is everything will scale proportionally by default because it is a vector object not a document flow object. 关于SVG的一件很酷的事情是,默认情况下,所有内容都会按比例缩放,因为它是一个矢量对象,而不是文档流对象。

This example will demonstrate the technique 此示例将演示该技术

<!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>

You can add images to SVG to achieve what you need. 您可以将图像添加到SVG以实现所需。

https://jsfiddle.net/tnt1/3f23amue/ https://jsfiddle.net/tnt1/3f23amue/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM