Exploring the dynamics of interaction using D3.js

I am currently experimenting with simulating gravitational forces acting on particles as they move towards a central point in space. Specifically, I am attempting to tweak the provided code so that the particles experience a slight deviation from their path due to an orange node before reaching a blue node. My challenge lies in visualizing this concept within D3.js force-directed layouts. Any assistance or guidance on how to achieve this effect would be highly appreciated. Please refer to the image and code snippet below:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <title>Custom Gravitational Forces Layout - Focal Shift</title>
    <script type="text/javascript" src="http://d3js.org/d3.v2.min.js?2.8.1"></script>
    <style type="text/css">

circle {
  stroke: #fff;
}

svg {
  fill: #fff;
  stroke: #000;
}

    </style>
  </head>
  <body>
    <div id="body">
      <div id="chart"></div>
    </div>
    <script type="text/javascript">

var w = 1280,
    h = 800,
    color = d3.scale.category10();

var force = d3.layout.force()
    .gravity(0)
    .charge(-5)
    .linkStrength(0)
    .size([w, h]);

var links = force.links(),
    nodes = force.nodes(),
    centers = [
      {type: 0, x: 3 * w / 6, y: 2 * h / 6, fixed: true},
      {type: 1, x: 4 * w / 6, y: 4 * h / 6, fixed: true}
    ];

var svg = d3.select("#chart").append("svg:svg")
    .attr("width", w)
    .attr("height", h);

svg.append("svg:rect")
    .attr("width", w)
    .attr("height", h);

svg.selectAll("circle")
    .data(centers)
  .enter().append("svg:circle")
    .attr("r", 12)
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .style("fill", fill)
    .call(force.drag);

force.on("tick", function(e) {
  var k = e.alpha * .1;
  nodes.forEach(function(node) {
    var center = centers[node.type];
    node.x += (center.x - node.x) * k;
    node.y += (center.y - node.y) * k;
  });

  svg.selectAll("circle")
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });

  svg.selectAll("line")
      .attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });
});

var p0;

svg.on("mousemove", function() {
  var p1 = d3.svg.mouse(this),
      a = {type: 0, x: p1[0], y: p1[1], px: (p0 || (p0 = p1))[0], py: p0[1]},
      b = {type: 1, x: centers[1].x, y: centers[1].y, fixed:true},
      link = {source: a, target: b};

  p0 = p1;

  svg.selectAll()
      .data([a, b])
    .enter().append("svg:circle")
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; })
      .attr("r", 4.5)
      .style("fill", fill)
    .transition()
      .delay(3000)
      .attr("r", 1e-6)
      .remove();

  svg.insert("svg:line", "circle")
      .data([link])
    .transition()
      .delay(3000)
      .each("end", function() {
        nodes.splice(nodes.indexOf(a), 1);
        nodes.splice(nodes.indexOf(b), 1);
        links.splice(links.indexOf(link), 1;
      })
      .remove();

  nodes.push(a, b);
  links.push(link);
  force.start();
});

function fill(d) {
  return color(d.type);
}

    </script>
  </body>
</html>

1 http://jsfiddle.net/fbW7T/1/ -- original animation.

[2] http://jsfiddle.net/fbW7T/2/ -- updated version after incorporating Lephix' approach.

Answer №1

Your inquiry has caught my interest :).
Modify your force.on("tick", function(e) {...}) with the code snippet below. I have introduced a new variable and included 10 lines of code within the function.
fr denotes the radius of a circular zone that particles should avoid around the orange node.

var fr = 100;
force.on("tick", function(e) {
  var k = e.alpha * .1;
  nodes.forEach(function(node) {
  var center = centers[node.type];
  node.x += (center.x - node.x) * k;
  node.y += (center.y - node.y) * k;

if (node.type == 0) {
    center = centers[1];
    while (Math.abs(node.x - center.x) < fr && Math.abs(node.y - center.y) < fr) {
        if (Math.abs(node.x - center.x) >= Math.abs(node.y - center.y)) {
            node.x += (node.x - center.x)/Math.abs(node.x - center.x);
        } else {
            node.y += (node.y - center.y)/Math.abs(node.y - center.y);
        }
    }
}
});

svg.selectAll("circle")
  .attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; });

svg.selectAll("line")
  .attr("x1", function(d) { return d.source.x; })
  .attr("y1", function(d) { return d.source.y; })
  .attr("x2", function(d) { return d.target.x; })
  .attr("y2", function(d) { return d.target.y; });
});

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

utilizing a returned list from a controller in an ajax request

When using an ajax call to store data in a database and the controller returns a list of commentObjects, how can this list be accessed in a JSP file? function StoreCommentAndRefreshCommentList(e) { var commentData = document.getElementById(ActualComme ...

When transferring JSON to JavaScript within Laravel, the JSON data gets converted into HTML entities by JavaScript

Within my Laravel controller, I am constructing a multidimensional associative array: $trendChart = Array ( "series" => Array ( "data" => Array(1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5) ), "xaxis" => Arr ...

Manipulate and scale with jQuery

I am currently utilizing the jQueryUI library with its Draggable and Resizable functionalities to resize and drag a div element. However, I am encountering some unexpected behavior where the div jumps outside of its container upon resizing. How can I resol ...

Calculating the average value of an attribute in an array using Mongodb (Mongoose)

Seeking assistance with a query to find sellers near users based on location input and sorting them by average rating. Is this achievable? Snippet of the model including an array of reviews: const sellerSchema = new mongoose.Schema({ _id: Mongo ...

What methods are available for transferring information between nodejs and puppeteer?

Recently, I developed a nodejs application that kicks off from index.js. Within index.js, puppeteer is launched and bot.js is injected into a headless-api page using the addScriptTag function. In my implementation, index.js sets a cookie to pass initial v ...

Add a click function to an element in a grid when it is databound

In my TypeCtrl ES6 class angular controller, I am using a kendo datagrid directive with a template for grid config options. Within the grid template, I need to call a method from the TypeCtrl class when a span within the row is clicked. However, the functi ...

Tips for incorporating WinBox JS into Angular applications

I've been experimenting with the WinBoxJS JavaScript library, and I'm familiar with using it in plain JS. However, I'm now attempting to integrate it into my Angular project. Can anyone guide me on how to achieve this? https://www.npmjs.com/ ...

What could be causing that unusual behavior within the quasar framework's select CSS?

I am facing an issue with a select control that needs to be aligned on the right side of the screen. Despite using HTML and CSS to achieve this, there is strange behavior when I initially click on the control. It breaks the options layout, but as I navigat ...

Retrieving historical states of an object in AngularJS

In the process of building a component with multiple select type inputs, each containing required options. When a required field is selected, it is removed from the 'requiredFields' array and added to the 'requiredFieldsRemoved' array. ...

Having trouble getting anime.js to function properly in an Ionic 3 project?

I have been attempting to incorporate anime.js into my Ionic 3 project, but I keep encountering an error when using the function anime({}) in the .ts file. Error: Uncaught (in promise): TypeError: __webpack_require__.i(...) is not a function TypeError: _ ...

Inside nested ng-transclude, the AngularJS directive isolates the scope

I've been scouring the internet for a solution to my problem, but I still haven't found it. In my application, I have a directive that enables users to sort and search through various lists of items. These items can vary in type and usage, leadi ...

Converting HTML into an object using $compile

I am currently working on calling an HTML template and want to bind the data with Angular. I successfully retrieve the data to bind and the HTML, but when I try to compile it, it returns all the HTML binded as an object. How can I convert it back to plain ...

Instructions on setting up a custom HTTPS server using the Alexa ask-cli

I am facing an issue with deploying my Alexa skill using the alexa-cli tool (https://www.npmjs.com/package/ask-cli). Whenever I try to deploy my skill with an https server, I encounter the following error: ◞ Creating new skill...Call create-skill err ...

Having Trouble Creating the production APK in React Native

Having trouble generating an APK after following the steps outlined in the documentation. Build Failed even though I tried: 1. cd android 2. gradlew clean "build Successful" 3. gradlew assembleRelease "BUILD FAILED" with this Erro ...

Utilize Tailwind CSS in React to dynamically highlight the active navigation item on click

Check out my navigation bar code: <nav className="bg-white shadow dark:bg-gray-800"> <div className="container flex items-center justify-center p-6 mx-auto text-gray-600 capitalize dark:text-gray-300"> <Link ...

Moving the left side of the screen using draggable feature in JQuery

I'm trying to figure out how to determine the offset of the left side of the screen. I've managed to calculate the offset for the right side, as shown in the example below. However, I also need to do the same for the left side, where the text sho ...

The dropdown menu vanishes from sight as soon as the cursor moves away from a link

Recently, I encountered an issue while trying to create a dropdown menu using Jquery. The problem arose when attempting to select the second link, as the entire menu would disappear. Additionally, is there a way to ensure that only one dropdown menu is vis ...

JavaScript Error: Unable to update the id property of the object due to read-only permissions

As I loop through an array and build another array based on it, I encounter an error during execution: TypeError: Cannot assign to read only property 'id' of object '#' const finalItems: any = []; data.items.forEach((parent: any) = ...

How to customize the color of Navbar pills in Bootstrap 4 to fill the entire height

Is there a way to ensure that the background of nav-items is completely filled with color rather than just partially? I attempted to use Bootstrap pills, but it did not achieve the desired effect. I also experimented with my own CSS, but encountered simil ...

The dropdown component in React TypeScript may have an undefined object

I'm currently working on a dropdown component, but TypeScript is throwing errors for the options.map and selectedOption.title cases: import React, { useRef,useState, useEffect } from "react"; import useToggle from '../hooks/useToggle&ap ...