Javascript数学“绘制”多个其他矩形周围的矩形,以实现背景效果

时间:2017-03-08 09:30:31

标签: javascript jquery css math position

注意:我会将 overlay 一词与 backdrop 互换使用。

我目前正在制作指南模式,并突出显示元素,使它们从较暗的半透明背景中脱颖而出。

所以基本上,我有一个我想要不覆盖的元素的选择器,然后用半透明的黑暗div来包围它,模拟带有排除元素的叠加。

我的解决方案适用于一个突出显示的元素,但当该数字变为2+时,很难计算如何将黑色div放在这些元素周围。事情是:突出显示的需求会因页面而异 - 这并不像那些多个元素是静态的。

为了说明我的问题:

enter image description here

在这里你可以看到需要放入页面的不同盒子,以便用半透明的黑暗div来包围Box2和Box2,基本上用突出显示的元素模拟叠加效果。对于像这样的一个案例,我可以硬编码计算,一切都会好的,但如果 Box1比Box2高?那么如果他们不再水平重叠呢?如果Box3需要突出显示怎么办?

在任何一种情况下,我都不知道要放置多少个暗盒以及放置它们的位置。

在这种情况下,是否有任何数学公式可以帮助我?使用jQuery也是可能的,因为它包含在我的项目中。

我如何解决这个问题并使其可扩展(多个框,不同的位置)?

3 个答案:

答案 0 :(得分:9)

你过度思考! 您正在寻找的是使用某种HTML和CSS布局。

您必须使用与此类似的布局:

.container
    .overlay
    .box
    .box
    .box
    .box

诀窍是使用全宽,半透明覆盖并将需要突出显示的元素添加到前面。非常重要的是将pointer-events: none指定给叠加层,以便点击它!

.box的{​​{1}}值为z-index,而1的{​​{1}}值为.overlay。要突出显示某个z-index,请将其100设置为.box。这样它就会突出显示。

我现在正在移动设备上,但我在 Codepen 上放了一个基本的概念验证。单击框以突出显示它们,再次单击以撤消。使用多个盒子!

答案 1 :(得分:1)

您可以使用阴影更轻松地解决此问题。

然后,您只需要将屏幕分为两部分



body, html {
   height: 100%; 
 }

body {
    background-image: linear-gradient(45deg, yellow, tomato);
}
.mask {
    overflow: hidden;
    width: 50%; 
    height: 100%; 
    display: inline-block;
    position: relative;
}

#mask1 {
    left: 0px;
}

#mask2 {
    right: 0px;
}

.hole {
    width: 150px; 
    height: 90px;
    position: absolute;
    box-shadow: 0px 0px 0px 2000px rgba(0,0,0,0.5);
}

#mask1 .hole {
    left: 40px;
    top: 40px;
}

#mask2 .hole {
    left: 140px;
    top: 20px;
}

<div class="mask" id="mask1">
    <div class="hole"></div>
</div><div class="mask" id="mask2">
    <div class="hole"></div>
</div>    
&#13;
&#13;
&#13;

答案 2 :(得分:1)

考虑使用区域

虽然这里有很多好的答案,你可能想考虑移动@WearyAdventurer提出的元素,其他答案都没有真正解决原来的问题:

  

如何以一种看似包围其他元素的方式创建元素?

使用名为 Region 的数据类型可以最好地解决该问题的答案。区域允许您使用2-D屏幕空间块轻松执行设置操作:将区域与 区域组合,然后减去另一个区域,然后将结果转换为我可以渲染的一组矩形。区域存在于大多数窗口系统(MS Windows,X Windows,经典MacOS等)中,并且在大多数浏览器中被大量使用&#39;用于渲染元素的内部机制,但它们在JavaScript中令人惊讶地缺席。

或者在我写一个图书馆之前,他们一直缺席。

区域的基本逻辑有些复杂。有许多极端情况,处理可能出现的所有情况可能具有挑战性。我的实现Region2D使用不相交的行(带)不相交的矩形(1维区域),这与许多X Windows服务器的行为相同。其他实现使用空间分区算法,还有一些(如现代MacOS)使用路径或多边形渲染技术而不是区域。

基本理念

无论您使用哪种实施方式,基本理念都保持不变。在您的情况下,您从一个覆盖屏幕的大矩形开始,然后简单地减去您想要的两个(或三个,或四个或其他)矩形,然后询问区域这些操作产生的矩形。在JavaScript中,使用我的Region2D库,它看起来像这样:

var screenRegion = new Region([0, 0, viewportWidth, viewportHeight]);
var elemRegion1 = new Region(element1);
var elemRegion2 = new Region(element2);
var coverRegion = screenRegion.subtract(elemRegion1).subtract(elemRegion2);
var coverRectangles = coverRegion.getRects();

生成的矩形数组是具有x / y / width / height / top / left / {的简单对象{1}} / right坐标,因此您只需从每个元素中创建bottom元素,即可完成。

工作实施

所以这里是一个解决实际问题的解决方案,使用我的Region2D库来进行繁重的算法提升:

&#13;
&#13;
<div>
&#13;
// Generate regions for each of the objects.
var containerRegion = new Region2D($(".container")[0]);
var target1Region = new Region2D($(".target1")[0]);
var target2Region = new Region2D($(".target2")[0]);

// Subtract the targets from the container, and make an array of rectangles from it.
var coverRegion = containerRegion.subtract(target1Region).subtract(target2Region);
var coverRects = coverRegion.getRects();

// Create gray <div> elements for each rectangle.
for (var i = 0, l = coverRects.length; i < l; i++) {
    var coverRect = coverRects[i];
    var coverElement = $("<div class='cover'>");
    coverElement.css({
        left: (coverRect.x - 1) + "px", top: (coverRect.y - 1) + "px",
        width: coverRect.width + "px", height: coverRect.height + "px"
    });
    coverElement.appendTo($(".container"));
}
&#13;
.container, .target1, .target2, .cover { position: absolute; top: 0; left: 0; box-sizing: border-box; }
.target1, .target2 { border: 1px solid red; }
.container { width: 330px; height: 230px; border: 1px solid blue; }
.target1 { top: 40px; left: 40px; width: 100px; height: 80px; }
.target2 { top: 100px; left: 180px; width: 100px; height: 80px; }
.cover { background: rgba(0, 0, 0, 0.5); border: 1px solid #000; }
&#13;
&#13;
&#13;