Using Javascript math to create a backdrop effect by drawing rectangles around multiple other rectangles

Important Note: In this discussion, the term overlay will be used interchangeably with backdrop.

Currently, I am developing a guide mode where I emphasize certain elements by making them stand out against a darker semi-transparent background.

The approach involves using a selector to identify the element that should not be overlaid. Subsequently, I surround this specific element with semi-transparent dark divs to create an overlay effect while excluding the chosen element.

While this method works effectively for highlighting a single element, managing multiple highlighted elements poses a challenge. Calculating the placement of black divs around these varied elements becomes increasingly complex, especially considering that highlight requirements differ from one page to another and are subject to change.

To illustrate the issue:

https://i.sstatic.net/NGwOo.png

In the image linked above, you can visualize the arrangement of boxes required to surround Box1 and Box2 with semi-transparent dark divs, creating the overlay effect for highlighted elements. While manual calculations may suffice for one scenario like this, the complexity arises when dealing with scenarios where Box1 is positioned higher than Box2, or if they do not overlap horizontally anymore due to other elements on the page.

In such cases, determining the number of dark boxes needed and their exact placement becomes uncertain.

Is there a mathematical formula or a jQuery-based solution that could address this challenge efficiently? How can I develop a flexible approach that accommodates multiple boxes placed at various positions?

Answer №1

Your solution is simpler than you think! By utilizing a specific HTML and CSS structure, you can achieve the desired outcome.

Consider implementing a layout similar to the following:

.wrapper
    .overlay
    .item
    .item
    .item
    .item

The key is to incorporate a full-width, semi-transparent overlay and ensure that elements requiring emphasis are brought to the forefront. An essential aspect is setting pointer-events: none for the overlay to enable clicking through it!

Assign a z-index value of, for instance, 1 to each .item, while giving .overlay a z-index of 100. To highlight a specific .item, adjust its z-index to 101, making it stand out.

Although I'm currently using a mobile device, I've shared a rudimentary demonstration on Codepen. Simply click on the items to emphasize them, and click again to revert the highlighting. This method works effectively with multiple items!

Answer №2

To make this task easier, consider using a shadow technique.

Simply divide the screen into two sections:

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>    

Answer №3

Using Regions for Element Placement

Among the various suggestions provided, the concept of rearranging elements as proposed by @WearyAdventurer stands out. However, none of the responses directly address the core inquiry:

How can I design elements in a way that they enclose other elements?

The most effective solution to this query involves employing a data type known as a Region. Regions facilitate executing set operations on portions of 2-D screen space: merging one area with another and then excluding a different area, culminating in a collection of rectangles suitable for rendering. While prevalent in window systems like MS Windows, X Windows, and classic MacOS, regions are notably absent in JavaScript, until I developed a library to fill this void.

The implementation of regions entails intricate logic, navigating through numerous edge cases. My approach, termed Region2D, employs disjoint rows of distinct rectangles (1-dimensional regions), reminiscent of how many X Windows servers operate. Other methodologies incorporate spacial partitioning algorithms or alternate techniques such as pathing in modern MacOS.


Core Concept

Irrespective of the chosen implementation, the fundamental principle remains unchanged. In your scenario, initiate with a large rectangle covering the screen, systematically subtract the desired number of rectangles, and derive the resultant rectangle array from the operations. When utilizing my Region2D library in JavaScript, the process unfolds as follows:

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

The resulting array comprises simple objects with coordinates like x, y, width, height, top, left, right, and

bottom</code. You can easily create <code><div>
elements based on these values.


Implementing the Solution

Here's an operational implementation addressing the initial query, leveraging the Region2D library for detailed computation:

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

// Deduct targets from the container, generating an array of rectangles.
var coverRegion = containerRegion.subtract(target1Region).subtract(target2Region);
var coverRects = coverRegion.getRects();

// Craft 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/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4b392e2c222425792f0b7a657b657b">[email protected]</a>/plain/region2d.min.js"></script>

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I'm attempting to adjust the line spacing and text size with CSS, but I'm having trouble getting it to work

Having some trouble adjusting line height and font size with CSS Below is the HTML code: <h2>I've finally stopped searching for love by sniffing other dogs. I found the most attractive Corgi on TinDog. Woof.</h2> CSS code: h2{ font-fam ...

What is the best way to hand off slots to a descendant component in Vue 3?

Is it possible to have a component within a 'layout' component populate its slots? JS Fiddle <div id="app"> <layout> <page></page> </layout> </div> const app = Vue.createApp({}); ap ...

Laravel 4.2 email template not applying CSS inline style for text color

Working on setting up email functionality in Laravel 4.2 and I've got an email template ready to go. The data for the emails is stored in an array, but I'm running into an issue where if I pass a parameter like $variable, the styles are only bein ...

Leveraging HTML classnames for metadata purposes

Is it recommended to use descriptive class names in HTML that fully describe its content, such as navbar-static-8 for a fixed navbar with 8 items? Alternatively, should the metadata be separated into individual attributes like type="static" items="8"? I ...

Information sent by the Firefox TCP socket using the socket.send() method cannot be retrieved until the socket is closed

I am experiencing an issue while trying to send data from Firefox to a Java desktop application. My Java class functions as a server, and the Firefox script acts as a client. When I test it using another Java class called client.java, the data is successfu ...

Creating a variable to store the data retrieved from a package

Imagine you have a functioning code snippet like this: const myPackage = require('myPackage'); myPackage.internal_func(parameter).then(console.log); This outputs a JSON object, for example: { x: 'valX', y: 'valY' } ...

Explore an array of elements to find the correct objectId stored in mongodb

element, I am faced with a challenge of searching through an array of objects to find a key that contains nested object id for populating purposes. Exploring My Object { service: 'user', isModerator: true, isAdmin: true, carts: [ ...

Prevent the Focus on Submit Button in CSS

Whenever a text field is focused in Opera, the submit button ends up with an unsightly black border. A screenshot clearly shows this issue. At the bottom of the image, you can see how the textarea is focused and the submit button looks unappealing. Is th ...

What's the best way to prevent extra spacing when typing in a materialUI TextField?

Instructions for the user: Please input your first name without any spaces between characters. I attempted to implement the following code, however, it did not achieve the desired outcome. <TextField required id="name" label="First Name" ...

Get the host name using Node.js server without using the 'req' parameter

Currently, I am utilizing req.headers.host to identify the host name of the server, which works well when dealing with incoming requests at the server. However, I am curious about how one can determine the host name without a request (i.e. without req). T ...

Setting up Quasar plugins without using Quasar CLI: A step-by-step guide

I integrated Quasar into my existing Vue CLI project by running vue add quasar. Now I'm attempting to utilize the Loading plugin, but unfortunately, it's not functioning as expected. Here is the configuration setup for Quasar/Vue that I have in ...

Pasting a canvas over a div using CSS

My website features a <div> containing creatively styled rings with a design reminiscent of the android unlock pattern. The div showcases 9 dots that can be connected in various configurations. I'm looking to overlay a canvas on this setup to tr ...

Error encountered with the NextGen (Mirth) Connect and MongoDB Java driver connection

I'm currently in the process of setting up Mirth Connect Server 3.10.1 (Java version: 1.8.0_181) to write FHIR JSON documents to MongoDB. Following the instructions provided in this post, I have included the following drivers in my custom-lib/ directo ...

How to convert DateTime format from database to input type='datetime' using PHP

I am having trouble retrieving a column from the database of type datetime and passing it to an input box with the type 'datetime' in my form. Unfortunately, nothing is being passed. <input type="datetime-local" id="myDate"> <button id= ...

The perfect way to override jest mocks that are specified in the "__mocks__" directory

Within the module fetchStuff, I have a mock function named registerAccount that is responsible for fetching data from an API. To test this mock function, I've created a mock file called __mocks__/fetchStuff.ts. Everything seems to be functioning corre ...

How can I incorporate an Instanced Billboard feature into my Three.JS project?

I am trying to achieve a specific effect where all instances of a mesh face the camera. uniform vec2 size; uniform vec3 center; vec3 billboard(vec3 v, mat4 view) { vec3 up = vec3(view[0][1], view[1][1], view[2][1]); vec3 right = vec3(view[0][0], ...

Mapping Longitude and Latitude with TopoJSON and D3

Currently utilizing the UK Geo JSON found at this link to generate a UK SVG Map. The goal is to plot longitude and latitude points onto this map. The GeometryCollection place is being added to the map in the following manner: data.objects.places = { ...

There seems to be an issue with React js Stripe checkout functionality not being

I am attempting to integrate a default Stripe checkout form into my React.js application. <form action="/your-server-side-code" method="POST"> <script src="https://checkout.stripe.com/checkout.js" className="stripe-button" data-key="pk_ ...

Why is my popover not showing in AngularJS?

I've integrated this particular component into my project, but unfortunately, when I click on the icon, the popover does not appear. The expected behavior is that clicking on the icon should trigger the display of the popover, however, currently noth ...

Issues arise with selecting text and highlighting it in JavaScript functions

I am currently working on a fun little web application that allows users to select text and highlight it in any color they choose. Here is the progress I have made so far: function replaceSelectedText() { var sel, range; var replacementText, spanT ...