Embrace the D3js Force Layout barrier and dive right in

Currently, I am working on a force layout project. My main objective is to enable the nodes to avoid a particular div element placed in the center without utilizing gravity within the SVG. I have already implemented collision detection and bounding within the existing SVG structure.

The approach I am considering involves overlaying the SVG on top of the target div using absolute positioning and attempting to implement node avoidance logic within the tick function. However, this method is proving to be quite challenging. Are there any alternative approaches that could be more effective? Any guidance in the right direction would be greatly appreciated!

In addition to the primary issue, I am also interested in having the nodes fall into view from the top without using gravity. Since maintaining the spacing between nodes is crucial, the traditional focus method may not be suitable for this scenario. Iā€™m unsure how to proceed with this secondary requirement.

I have included my Javascript and CSS code below for reference

    width = parseInt(d3.select('#canvas').style('width'), 10),
    height = parseInt(d3.select('#canvas').style('height'), 10),
    padding = 30, // separation between circles
    radius = 70;

    //Set up the force layout
    var force = d3.layout.force()
        .gravity(0)
        .charge(0)
        .size([width, height]);

    //Append a SVG to the body of the html page.
    //Assign this SVG as an object to svg
    var svg = d3.select("#canvas").append("svg")
        .attr("width", width)
        .attr("height", height);

    //Read the data
    d3.json("dots.json", function(error, graph) {
        if (error) throw error;

        //Creates the graph data structure out of the json data
        force.nodes(graph.nodes)
            .start();


        //Do the same with the circles for the nodes - no
        var node = svg.selectAll(".node")
            .data(graph.nodes)
        .enter().append("g")
            .attr("class", "node")
            .call(force.drag);

        node.append("circle")
          .attr("r", radius)
            .style("fill", "black")
          .call(force.drag);

        node.append("text")
          .attr("dx", 0)
          .attr("dy", 5)
          .attr("height", 10)
          .attr("text-anchor", "middle")
          .text(function(d) { return d.name })
          .style("fill", "white");


        //Now we are giving the SVGs co-ordinates - the force layout
        //is generating the co-ordinates which this code is using to
        //update the attributes of the SVG elements
        force.on("tick", function (e) {

            node.attr("cx", function(d) {
                return d.x =
                Math.max(
                    radius,
                    Math.min(
                        width - radius,
                        d.x
                    )
                );
            }).attr("cy", function(d) {
                return d.y = Math.max(radius, Math.min(height - radius, d.y));
            });

              node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });


            node.each(collide(0.5)); //Added
        });

        function collide(alpha) {
          var quadtree = d3.geom.quadtree(graph.nodes);
          return function(d) {
            var rb = 2*radius + padding,
                nx1 = d.x - rb,
                nx2 = d.x + rb,
                ny1 = d.y - rb,
                ny2 = d.y + rb;

            quadtree.visit(function(quad, x1, y1, x2, y2) {
              if (quad.point && (quad.point !== d)) {
                var x = d.x - quad.point.x,
                    y = d.y - quad.point.y,
                    l = Math.sqrt(x * x + y * y);
                  if (l < rb) {
                  l = (l - rb) / l * alpha;
                  d.x -= x *= l;
                  d.y -= y *= l;
                  quad.point.x += x;
                  quad.point.y += y;
                }
              }
              return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
            });
          };
        }

        node.on("mousedown", function(d1, i) {
            var $this = d3.select(this);
            if(node.active) {
                $this = $this.transition()
                    .duration(1000)
                    .attr("stroke-width", 0)
                    .attr("r", radius);

                node.active = false;
            } else {
                $this = $this.transition()
                    .duration(1000)
                    .attr("stroke-width", 20)
                    .attr("stroke", "4DD2B6")
                    .attr("fill", "white")
                    .attr("r", radius * 2)
            }
        });

    });



#canvas, #playground {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1;
    overflow: visible;
    display: block;
}

#playground {
    height: 100%;
}

header {
    width: 320px;
    margin: 100px auto 50px;
    display: block;
    z-index: 10;
    background-color: red;
}

Answer ā„–1

Setting Boundaries

Managing collision detection can be complex since each node has the potential to collide with any other node. This is where the quad tree comes in handy, as it helps reduce the number of collisions that need to be checked. When discussing boundaries, things become more straightforward because there is only one boundary to consider. In your scenario, all you have to do is extend the dimensions of the boundary to encompass the occlusion area.

Falling Effect

Interpreting the term "fall in" can vary, but a possible approach is to initially set the center x and y values to the desired source point from which they should emanate. Then, enhance your boundary behavior to address what happens if nodes move beyond the confines of the SVG. This could involve implementing a custom gravity mechanism to determine the next x and y positions based on their current locations and the specified direction of movement. While the collision algorithm may not account for boundaries, it will still work to prevent nodes from overlapping as they descend.

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

Sync State with Data from API Query

I have a scenario where I need to fetch data from two different APIs and update their states separately. Afterward, I am iterating through the NBA data and looping through the animeData object to update the allData state, which will be an array of object ...

Having trouble locating the module '.outputserver ode_modulespiniadistpinia' in Nuxt3 and Pinia?

I recently integrated Pinia into my Nuxt3 project, and while everything works fine in development mode, I encountered an error when trying to access the application in production mode resulting in the website freezing. [h3] [unhandled] H3Error: Cannot find ...

Issues arise when attempting to delete messages that have already been retrieved

Having trouble removing messages from a specific user without any success: bot.js client.on("message", (message) => { if (message.content === '$deleteuser') { message.channel.fetchMessages({limit: 10}).then(collec ...

What are the steps to automatically populate the location or name in the trip advisor widget?

I have encountered an issue with my website where I have multiple hotel lists but the trip advisor widget only shows one. Is there a solution, such as a script or other method, that can use variables to automatically set the location or name in the widget? ...

Attempting to adjust the width of a text animation loaded with jQuery using Textillate, but encountering difficulties

I found a captivating animation on this website: http://codepen.io/jschr/pen/GaJCi Currently, I am integrating it into my project. #content { position: relative; margin-left: auto; margin-right: auto; width: 1000px; height: 700px; } ...

The blur() function in -webkit-filter does not seem to function properly in Vue.js

I'm having trouble implementing the -webkit-filter: blur() property. I tried using "filter" instead, but it still isn't working. Could this be a limitation of Vue.js or are there any other solutions available? <template> <div class=&qu ...

Clicking on text will open a popup div using HTML and CSS

I am looking to create a popup div instead of a popup window for my 'About' picture/page with the current button. Here is an example: ...

What is the best way to determine if an application has been installed on an Android device while browsing a website?

Let's set the scene: I've got a website that needs to use JavaScript to determine whether my app is already installed on the android device it's currently being used on. If the app is installed, the page will display a link (with a custom ...

Identify numbers and words within a sentence and store them in an array

Looking to split a string into an array based on type, extracting numbers and floats. The current code is able to extract some values but not complete. var arr = "this is a string 5.86 x10ā€˜9/l 1.90 7.00" .match(/\d+\.\d+|\d+&bsol ...

What is the best way to superimpose two images with the same width but varying heights, where one remains static and the other scrolls seamlessly

I'm in the process of creating a webpage that will feature a .png image of a computer with a transparent screen. Upon this image, I plan to overlay a screenshot of a website and allow users to scroll through it as if they were navigating a real webpag ...

Tips for adding a personalized close button to a Bootstrap modal

I need help with a Bootstrap modal in my project that has a close button positioned at the top right corner. I've used CSS to position the button, but it's not staying in one place consistently despite applying absolute positioning. I've tri ...

Is a CSS-only autoexpanding label possible within a list?

I am interested in having all the labels automatically expand to the size of the widest one. Below is the HTML structure: <div class="body"> <ul class="list"> <li> <span> <label>condition</label> ...

The full background width is not being displayed as 100% on the

Unexpectedly, the "full left secondary-bg" background division on this particular page (http://goo.gl/OU4MkW) is no longer spanning the full width of the screen and I am unable to figure out why. This website is WordPress-based and constructed using the sk ...

Implementing theme in Monaco editor without initializing an instance

I recently developed a web application incorporating Monaco Editor. To enhance user experience, I also integrated Monaco for syntax highlighting in static code blocks. Following guidance from this source, I successfully implemented syntax highlighting wit ...

Using Socket.io with Heroku

I encountered an issue with using Node.js and socket.io on Heroku. While it works without any problems on my local environment, once I deploy it to Heroku and try to access the website, it shows me an application error page. Even after checking the logs, I ...

Confirming the existence of a folder with AngularJS

Currently, I am attempting to determine if a folder exists so that I can make decisions on which files to include using ng-include. This is what I have so far: $scope.isVisible = { buttons: checkForClientOverwride('buttons'), it ...

Determining neutering status of transferable object in JavaScript Float32Array

I am utilizing transferable objects in the communication between my main thread and physics worker. The Float32Array is being shared back and forth with great efficiency. How can I determine if a Float32Array has been neutered? For instance, here is an ex ...

Exploring ways to retrieve item metadata from a Stripe checkout session

When setting up a Checkout session, I dynamically create prices using the price_data and product_data properties. I include metadata for each item within the product_data.metadata property. However, after a successful payment is made, I retrieve the sessi ...

How to combine two tables in Sequelize using a one-to-many relationship

I'm currently working with two models: User and Foto. In my application, each User can have multiple fotos, and each foto is associated with only one user. My challenge lies in using the include function. I am able to use it when querying for the us ...

What steps do I need to take to incorporate the Google API into my Chrome extension's content script

I am currently attempting to display labels using the Gmail API within a content script. Below are snippets from my manifest.json and content-script.js files: { "name": "Append Test Text", "description": "Add test123 to body", "version": "1.0", "p ...