2017-03-08 37 views
10

注意:我將使用這個詞覆蓋可互換Javascript數學「繪製」矩形圍繞多個其他矩形實現背景效果

我目前工作的一個引導模式,我強調的元素,使他們從黑暗的半透明背景中脫穎而出。

所以基本上,我有我想要不被覆蓋的元件的選擇,然後我圍繞着它與半透明的深的div,模擬的覆蓋與排除的元件。

我的解決方案的一個突出顯示的元素的偉大工程,但如果這個數字變成2+,變得難以計算出如何將圍繞這些元素的黑色div的。事情是:突出顯示的需求在頁面之間會有很大的不同 - 它不像那些多個元素是靜態的。

所以來說明我的問題:

enter image description here

在這裏,您可以看到,需要投入的頁面,以圍繞BOX2和BOX2與半透明的黑色div會在不同的盒子,基本上用突出顯示的元素模擬疊加效果。對於一個情況下,像這樣的,我可以硬編碼計算,一切都將被罰款,但如果 BOX1上漲超過BOX2高?那麼如果他們不再水平交疊呢?如果有需要突出顯示的Box3會怎麼樣?

在任何情況下,我不知道有多少黑框的地方,在哪裏放置它們。

在這種情況下是否有任何數學公式可以幫助我? jQuery的使用也是可能的,因爲它包含在我的項目中。

如何我會解決這個問題,並使其擴展(多盒,不同的位置)?

+1

寫一個從另一個矩形減去的函數,cr回報一些小矩形的列表。現在,將該函數應用於邊界框和第一個突出顯示的矩形。然後,將該函數應用於從前一次調用返回的每個矩形。沖洗並重復。另請參閱https://en.wikipedia.org/wiki/Constructive_solid_geometry獲取更優化的算法 –

+1

嘿!我提交了一個工作解決方案,你可以看看它嗎? –

+0

你真正想要的是什麼叫做_Region_數據類型。區域在二維空間的矩形有界塊上執行聯合/交集/減法,並且被設計爲使得您可以容易地從矩形構造它們並且從它們解構矩形。我之前用C編寫過代碼,在一般情況下它很複雜。大多數圖形用戶界面原生地包含一個區域類型(Windows,X和Mac都有),並將其用於大多數渲染,但似乎並沒有我能找到的JavaScript實現:令人驚訝的是,似乎沒有NPM包可用去做這個。 –

回答

9

你正在超越! 您正在尋找的東西可以通過特定的HTML和CSS佈局來實現。

你必須使用一個類似的佈局:

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

訣竅是使用全寬,半透明疊加並把需要高亮,以正面的元素。非常重要的是將pointer-events: none分配到疊加層,以便您可以點擊它!

.box有,比方說,1.overlay100一個z-indexz-index值。爲了突出顯示某個.box,請將其z-index設置爲101。這樣它會突出顯示。

我現在在手機上,但我在Codepen上提出了一個基本的概念驗證。點擊框突出顯示它們,再次點擊撤消。適用於多個盒子!

+0

這很好用!只是要成爲「那個人」,根據你的最低支持目標是什麼,請記住,IE 10及以下版本不支持'pointer-events'屬性。 –

+0

@JonathanBowman感謝您的反饋!我意識到這一點,並有一個IE特定的黑客涉及'\ 9' iirc。 OP沒有說任何有關瀏覽器支持的內容,所以我認爲這不是問題。事實上,OP沒有說任何** **,也許他不想放棄賞金:D –

+0

哈哈,好吧,讓我們希望不是這樣:)我需要檢查那是因爲指針事件真的很有用,但我知道一些公司(比如我工作的公司),仍然有客戶在IE 9上擔心。是的,你是完全正確的,他沒有提到客戶支持,我只是知道有時候你會被類似的東西咬傷,所以我想提醒一下。謝謝你提供解決方法的技巧,我會查找它! –

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>

1

屏幕考慮使用地區

雖然有一些很好的答案在這裏,你可能會考慮移動像@WearyAdventurer這樣的元素,但其他答案都沒有解決原始問題:

如何創建元素使其看起來圍繞其他元素?

這個問題的答案的問題是最好的解決使用一個被稱爲地區的數據類型。區域允許您使用大塊二維屏幕空間輕鬆地執行設置操作:將這個區域與區域區域再減去區域的另一個區域,然後將結果轉換爲我可以渲染的一組矩形。區域存在於大多數窗口系統(MS Windows,X Windows,經典的MacOS等)中,並且在大多數瀏覽器的內部機制中用於渲染元素,但它們在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/right/bottom座標簡單對象,所以你只要從每個元素創建<div>元素,然後就完成了。


工作實現

所以這裏有一個解決方案所呈現,用我的Region2D庫來完成繁重的算法提升實際問題的工作實施:

// 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")); 
 
}
.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; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://unpkg.com/[email protected]/plain/region2d.min.js"></script> 
 

 
<div class="container"> 
 
    <div class="target1"></div> 
 
    <div class="target2"></div> 
 
</div>