将 div 定位在变高图像的特定区域

9

我正在尝试将一个div定位在变高度的图片上方,并想知道如何最好地处理这种情况。例如,在下面的示例中,我正在尝试将红色正方形定位在图片中的注册商标符号上:Fiddle

我的HTML/CSS如下:

<img src="http://cisloandthomas.com/wp-content/uploads/2015/12/Shrunken-Banner-Wide-Ends-1140x200.jpg" class="background">
<div class="overlay"></div>

.background {
  height: 100%;
  position: absolute;
  margin-top: -61px;
}

.overlay {
  position: absolute;
  height: 20px;
  width: 20px;
  background: red;
}

我正在使用以下JS将红色div定位在图像上方:

var resizeOverlay = function() {
  var windowHeight = $(window).height();

  var left = windowHeight * 1.07;
  var bottom = (windowHeight * .63) + 61;

  $(".overlay").css({
    "left": left,
    "bottom": bottom
  });
};

$(document).ready(resizeOverlay);
$(window).resize(resizeOverlay);

结果并不理想,因为我只是建立了两个线性模型来计算x和y的偏移量。其他人会如何处理这个任务?

2
我宁愿使用Photoshop。 - Naeem Shaikh
1
你做得很好,似乎是正确的。当你改变高度时,它会改变图像的尺寸,但正方形的形状保持不变。因此它们无法完全匹配。 - Himanshu
感谢@NaeemShaikh,但如果我使用Photoshop将叠加层烧录到图像中,仍然需要在覆盖红色正方形的页面区域上添加点击监听器,因此任务将继续存在。同样感谢Himanshu,但我想知道如何以非任意的方式处理该任务(我正在猜测和检查,但希望能够机械地推导出公式)。 - duhaime
@duhaime.. 您必须手动调整每个图像的位置..没有其他选项。 - Naeem Shaikh
4个回答

9

可以通过CSS和对标记的少量更改来实现这一点

您示例中的图像是相对于视口高度缩放的 - 高度始终为100%,宽度由浏览器根据其宽高比动态计算。

要定位同样的叠加效果,需要应用相同的缩放。为此,可以添加一个容器,该容器将适合视口高度并按比例缩放到图像的宽度,然后可以相对于其定位叠加效果,并与图像成比例地缩放。

需要进行以下修改:

  • 在容器中包装.background.overlay(在此实例中称为#container
  • #container设置为以下属性:
    • height: 100vh; - 这将使其填充整个视口高度
    • margin-top: -61px; - 从您的示例中继承
    • position: relative; - 确保.overlay相对于此容器定位
    • width: 570vh; - 这将确保容器以与图像相同的速率缩放。这是通过找到现有图像的宽高比 - 1140 x 200是57:10的宽高比,因此200(px) * 5.7 = 1140(px)转换为100(vh) * 5.7 = 570(vh)
  • .background设置以下属性:
    • height: 100%; - 以确保其以类似于示例的方式调整大小,它将填充整个视口高度。宽度将相对于此进行缩放
  • .overlay设置以下属性:
    • background: red; - 从您的示例中继承
    • height: 6vh; - 由于图像是相对于视口高度缩放的,因此这将确保叠加效果以相同的速率缩放
    • left: 18.3%; - 将叠加效果定位在注册符号上指定的区域
    • position: absolute; - 相对于容器定位叠加效果
    • top: 29%; - 将叠加效果定位在注册符号上指定的区域
    • width: 6vh; - 由于图像是相对于视口高度缩放的,因此这将确保叠加效果以相同的速率缩放

$(".overlay").click(function() {
  alert("Clicked")
});
#container {
  height: 100vh;
  margin-top: -61px;
  position: relative;
  width: 570vh;
}
.background {
  height: 100%;
}
.overlay {
  background: red;
  height: 6vh;
  left: 18.3%;
  position: absolute;
  top: 29%;
  width: 6vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <img alt="" class="background" src="http://cisloandthomas.com/wp-content/uploads/2015/12/Shrunken-Banner-Wide-Ends-1140x200.jpg">
  <div class="overlay"></div>
</div>

JS Fiddle - 更改结果窗口的高度,覆盖层应相应地重新定位。


2
昨天我走回家时意识到这个问题其实非常简单。
图片的比例是恒定的,覆盖层有两个值:x位置和y位置。 x位置只是图像宽度的一些分数,而y位置是图像高度的一些分数。
因此,可以使用两个浮点值{0,1}表示覆盖层的位置:一个用于x轴上的覆盖层位置,另一个用于y轴。然后,只需将这些值乘以图像的宽度和高度(分别)即可找到覆盖层的适当x,y位置。
要使覆盖层始终保持在兴趣点上方(即{0:max-image-x},{0:max-image-y}),只需要从计算出的x,y位置中减去覆盖层div宽度的一半即可。

1
这里是fiddle,我在发布后意识到了你问题的结尾...不管怎样,我把答案留在这里,因为至少它的位置很准确。我认为没有比你已经尝试过的方法更好的方法了。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <style type="text/css">
        html, body, div, span, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, code,del, dfn, em, img, q, dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td{margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}
        body{line-height:1.5;}
        table{border-collapse:separate;border-spacing:0;}caption, th, td{text-align:left;font-weight:normal;}
        table, td, th{vertical-align:middle;}
        blockquote:before, blockquote:after, q:before, q:after{content:"";}blockquote, q{quotes:"" "";}
        a img{border:none;}

        .background {
            height: 100%;
            position: absolute;
            margin-top: -61px;
        }

        .overlay {
            position: absolute;
            background: red;
            -moz-border-radius:100%;
            -webkit-border-radius:100%;
            border-radius:100%;
        }
    </style>
</head>
<body>
<script type="text/javascript">
    var resizeOverlay = function() {
        var l=515,
                t=145,
                $b=$('.background'),
                $o=$('.overlay'),
                o_w=25,
                o_h=25;
        var b_h=$b.height();
        var ratio=$b.width()/2800;
        $o.css({
            left:parseInt(l*ratio,10)+'px',
            top:parseInt(t*ratio-61,10)+'px',
            width:parseInt(o_w*ratio,10)+'px',
            height:parseInt(o_h*ratio,10)+'px'
        });
        console.log('background_height',b_h);
    };

    $(document).ready(resizeOverlay);
    $(window).resize(resizeOverlay);
</script>
<img src="http://cisloandthomas.com/wp-content/uploads/2015/12/Shrunken-Banner-Wide-Ends-1140x200.jpg" class="background">
<div class="overlay"></div>
</body>
</html>

0
多年之后,我意识到在图像的特定区域上放置元素的最佳方法是使用SVG,在SVG中添加图像,并在图像的感兴趣点上定位SVG元素。 这个网站有一个例子,其中建筑物的图像上叠放着楼层,悬停在某一楼层(例如22楼)会突出显示该楼层。

enter image description here

这是相关的标记:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="4.5 0 980.9 545.9" x="0px" y="0px">
<g>
    <image height="546" overflow="visible" transform="matrix(0.9999 0 0 0.9999 4.4815 -0.9215)" width="981" href="https://www.360statestreet.com/wp-content/themes/statestreet360/images/floorplans/bg-floor_plans.jpg"/>
</g>
<g id="Floors">
    <polygon class="floor Floor7" fill="rgba(102,199,198,0.8)" id="Floor7" opacity="0" points="424,309 450,319 449,320 624,385 632,383 663,394 715,376 715,389 665,409 629,398 624,398 449,333 450,332 424,321" values="th"/>
    <polygon class="floor Floor8" fill="rgba(102,199,198,0.8)" id="Floor8" opacity="0" points="424,297 450,307 449,310 624,373 632,372 663,383 715,364 715,376 666,396 629,384 624,385 450,323 450,320 424,310" values="th"/>
    <polygon class="floor Floor9" fill="rgba(102,199,198,0.8)" id="Floor9" opacity="0" points="424,287 450,297 450,299 625,361 633,360 665,371 715,352 715,365 667,382 630,372 624,374 450,311 450,308 424,299" values="th"/>
    <polygon class="floor Floor10" fill="rgba(102,199,198,0.8)" id="Floor10" opacity="0" points="424,275 450,284 450,287 627,349 634,345 668,358 715,340 715,353 668,372 630,359 628,361 450,300 450,296 424,287" values="th"/>
    <polygon class="floor Floor11" fill="rgba(102,199,198,0.8)" id="Floor11" opacity="0" points="424,263 450,271 450,275 627,337 634,334 667,345 715,327 715,340 667,358 635,346 627,349 450,287 450,284 424,275" values="th"/>
    <polygon class="floor Floor12" fill="rgba(102,199,198,0.8)" id="Floor12" opacity="0" points="424,252 450,261 450,264 627,324 635,322 667,332 715,315 715,327 668,346 635,334 627,337 450,276 450,274 424,265" values="th"/>
    <polygon class="floor Floor13" fill="rgba(102,199,198,0.8)" id="Floor13" opacity="0" points="424,240 451,249 451,251 628,310 635,308 668,319 715,301 715,315 668,333 635,322 628,325 450,265 450,263 424,254" values="th"/>
    <polygon class="floor Floor14" fill="rgba(102,199,198,0.8)" id="Floor14" opacity="0" points="424,228 451,237 451,240 628,297 635,296 668,307 715,289 715,302 668,320 634,309 628,310 450,252 450,250 424,241" values="th"/>
    <polygon class="floor Floor15" fill="rgba(102,199,198,0.8)" id="Floor15" opacity="0" points="424,216 451,225 451,227 628,284 634,284 668,295 715,277 715,290 670,307 634,295 628,298 450,240 450,238 424,229" values="th"/>
    <polygon class="floor Floor16" fill="rgba(102,199,198,0.8)" id="Floor16" opacity="0" points="424,203 451,213 451,216 628,272 634,271 668,282 715,265 715,277 669,295 634,284 628,286 450,228 450,225 424,216" values="th"/>
    <polygon class="floor Floor17" fill="rgba(102,199,198,0.8)" id="Floor17" opacity="0" points="424,192 451,203 451,205 628,260 634,259 668,270 715,253 715,265 669,282 634,271 628,273 450,216 450,213 424,204" values="th"/>
    <polygon class="floor Floor18" fill="rgba(102,199,198,0.8)" id="Floor18" opacity="0" points="424,182 451,191 451,193 629,248 634,246 668,257 715,240 715,253 669,270 634,258 628,261 450,205 450,202 424,194" values="th"/>
    <polygon class="floor Floor19" fill="rgba(102,199,198,0.8)" id="Floor19" opacity="0" points="424,171 451,179 451,181 629,235 630,233 668,245 715,228 715,240 669,257 634,246 628,249 450,193 450,190 424,183" values="th"/>
    <polygon class="floor Floor20" fill="rgba(102,199,198,0.8)" id="Floor20" opacity="0" points="424,160 451,167 451,170 629,224 632,222 668,232 715,215 715,228 669,245 634,234 628,237 450,182 450,179 424,171" values="th"/>
    <polygon class="floor Floor21" fill="rgba(102,199,198,0.8)" id="Floor21" opacity="0" points="424,148 450,156 451,160 629,212 633,209 668,220 715,204 715,216 669,233 634,222 628,225 450,172 450,168 424,160" values="st"/>
    <polygon class="floor Floor22" fill="rgba(102,199,198,0.8)" id="Floor22" opacity="0" points="424,138 450,144 451,147 629,200 633,198 668,207 715,191 715,205 669,221 634,212 628,214 450,162 450,158 424,150" values="nd"/>
    <polygon class="floor Floor23" fill="rgba(102,199,198,0.8)" id="Floor23" opacity="0" points="424,126 452,135 451,136 629,187 633,185 668,195 715,181 715,194 669,211 634,200 628,202 450,149 450,147 424,139" values="rd"/>
    <polygon class="floor Floor24" fill="rgba(102,199,198,0.8)" id="Floor24" opacity="0" points="424,116 452,124 451,125 629,176 633,173 668,183 715,166 715,180 669,195 634,187 628,189 450,137 450,135 424,129" values="th"/>
    <polygon class="floor Floor25" fill="rgba(102,199,198,0.8)" id="Floor25" opacity="0" points="424,103 452,111 451,113 629,162 633,160 668,170 715,155 715,168 669,183 634,173 628,176 450,127 450,125 424,117" values="th"/>
    <polygon class="floor Floor26" fill="rgba(102,199,198,0.8)" id="Floor26" opacity="0" points="424,91 452,99 451,101 629,150 633,148 668,157 715,142 715,156 669,171 634,161 628,164 450,115 450,112 424,105" values="th"/>
    <polygon class="floor Floor27" fill="rgba(102,199,198,0.8)" id="Floor27" opacity="0" points="424,80 452,88 451,90 629,138 634,135 668,144 715,130 715,143 669,158 634,149 628,151 450,103 450,100 424,93" values="th"/>
    <polygon class="floor Floor28" fill="rgba(102,199,198,0.8)" id="Floor28" opacity="0" points="425,69 452,76 451,78 629,126 634,123 668,132 715,118 715,131 669,145 634,136 628,139 450,91 450,88 424,81" values="th"/>
    <polygon class="floor Floor29" fill="rgba(102,199,198,0.8)" id="Floor29" opacity="0" points="449,59 449,63 448,65 513,81 525,78 557,86 557,92 622,108 632,109 681,95 681,94 681,104 715,112 664,128 630,120 622,121 449,76 446,72 426,66" values="th"/>
    <polygon class="floor Floor30" fill="rgba(102,199,198,0.8)" id="Floor30" opacity="0" points="451,54 513,70 527,67 556,73 557,79 623,95 681,81 680,95 632,109 622,109 556,93 555,85 526,79 513,82 451,66" values="th"/>
    <polygon class="floor Floor31" fill="rgba(102,199,198,0.8)" id="Floor31" opacity="0" points="451,40 513,55 527,52 556,59 557,65 623,81 680,68 681,81 632,94 622,96 556,79 555,73 526,67 513,70 451,53" values="st"/>
</g>
</svg>

建筑图像存储在image标签中,每个楼层都有一个放置在图像上方的polygon。SVG调整规则处理SVG大小,所有子元素都随着重新缩放的图像进行缩放!


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