d3.js attempting to animate data, but each time the data is altered it is always perceived as new

I have a JSON dataset that consists of an array of frames, with each frame containing an array of 10 nodes. Each node is represented as a dictionary with the node id and x,y coordinates. My objective is to devise a d3 animation that smoothly transitions between the positions of nodes in consecutive frames.

To achieve this, I initiated setInterval(...) to facilitate the transitions to the next set of node positions. Nevertheless, instead of smoothly updating the existing nodes through the transition process, a batch of new nodes are being added. I speculate whether I might be erring in implementing the key function, or if there's another flaw at play?

Below is an excerpt illustrating what the JSON data appears like:

[[{"y": "0.898287995669", "x": "0.824201870934", "v": "0"}, {"y": "0.738482578278", "x": "0.645352934631", "v": "1"}, {"y": "0.12255740116", "x": "0.113578656145", "v": "2"}, {"y": "0.603047665154", "x": "0.609252770235", "v": "3"}, {"y": "0.497780597993", "x": "0.490370637301", "v": "4"}, {"y": "0.450309984776", "x": "0.428403273731", "v": "5"}, {"y": "0.512235180495", "x": "0.552584811488", "v": "6"}, {"y": "0.808721117001", "x": "0.829379563316", "v": "7"}, {"y": "0.771161177414", "x": "0.378854605349...

And here's my current code snippet:

var width = 960,
    height = 500;
var padding = 10;

// Inverted due to SVG's inverted y axis
var yscale = d3.scale.linear().domain([1,0]).range([padding, height - padding]);
var xscale = d3.scale.linear().domain([0,1]).range([padding, width - padding]);


var color = d3.scale.category20();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

d3.json("out.json", function(error, json) {
  if (error) return console.warn(error);
  var graphFrames = json;
  startDrawing(graphFrames);
});


function drawFrame(graphFrame) {
    // DATA JOIN
    // Join new data with old elements, if any.
    var nodes = svg.selectAll("node")
        .data(graphFrame, function(d){ return d.v; });


    // UPDATE
    // Update old elements as needed.
    nodes.transition()
        .duration(750)
        .attr("cx", function(d) { return xscale(d.x); })
        .attr("cy", function(d) { return yscale(d.y); });


    // ENTER
    // Create new elements as needed.
    nodes.enter().append("circle")
        .attr("class", "node")
        .attr("r", 5)
        .attr("cx", function(d) { return xscale(d.x); })
        .attr("cy", function(d) { return yscale(d.y); })
        .style("fill", function(d, i){ return color(d.v % 20); });

    // EXIT
    // Remove old elements as needed.
    //nodes.exit().remove();
}


var nextFrameIdx = 1;
function startDrawing(graphFrames){
    // Initial display.
    drawFrame(graphFrames[0]);

    // Draw the next set of node coordinates at regular intervals
    setInterval(function() {
        drawFrame(graphFrames[nextFrameIdx]);
        nextFrameIdx = (nextFrameIdx + 1) % graphFrames.length;
    }, 1500);

}

Answer №1

Your approach was almost there! Just ensure that you are selecting the correct elements you have defined using .attr("class", "node");. So, modify your code to:

var nodes = svg.selectAll(".node")
    .data(graphFrame);

Previously, you were trying to select on "node" which does not exist, causing the enter selection to always be triggered. It's also acceptable to stick with the default index-based data binding since you are essentially manipulating the same items (=same index) in the selection.

For a functional example, check out this live demonstration on PLUNK.

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

Guide to implementing onhashchange with dynamic elements

Hey there! I've encountered a problem with two select boxes on my webpage, each in different anchors (one on the page, the other in an iframe). What I'm trying to achieve is for the code to recognize which anchor it's in and then pass the se ...

What is preventing me from making a call to localhost:5000 from localhost:3000 using axios in React?

I have a React application running on localhost:3000. Within this app, I am making a GET request using axios to http://localhost:5000/fblogin. const Login = () => { const options = { method: "GET", url: "http://localhost:5000/fblogin", ...

Easily create clickable words in Flutter by extracting specific words from a JSON String

In my JSON response, I receive a set of questions. My goal is to split these questions into words and compare them with another JSON response. When there's a match, I want to highlight the matching words and make them clickable to display a pop-up sho ...

Do I have to create all the classes returned when consuming a JSON web service in Angular/Typescript?

I would like to access this service: https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY I am interested in extracting only two pieces of data: "location" : { " ...

Tips for handling catch errors in fetch POST requests in React Native

I am facing an issue with handling errors when making a POST request in React Native. I understand that there is a catch block for network connection errors, but how can I handle errors received from the response when the username or password is incorrec ...

Having trouble generating a bin executable for my npm package

Referencing: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#bin I am attempting to generate a "binary" for my npm package. The structure of my package.json is as follows: { "name": "@internal/my-exe", "version": "0.0.0", "type": "commo ...

Is there a way to handle templates in AngularJS that is reminiscent of Handlebars?

Is there a way to handle an AngularJS template using a syntax similar to Handlebar? <script type="text/ng-template" id="mytemplate"> Name is {{name}} </script> I know how to retrieve the template using $templateCache.get('mytemplate&ap ...

Utilizing JavaScript to assign object properties (column names) from an Array of Objects to a specific row and column header

I am currently in the process of implementing a mapping function to display data from an array of objects, initially stored in localStorage, into a table using Material-UI Table. The goal is to map all the specific column names into corresponding Table Ce ...

Using D3.js to plot data points on a topojson map's coordinates

Having difficulty converting latitude and longitude coordinates to "cx" and "cy" positions on my SVG map created with d3 and topojson. Despite researching solutions online, I am unable to successfully implement the conversion process. Each time I try to co ...

Tips on building a blog using solely index.html, style.css, and script.js files

Looking for inspiration for blog listing pages? Check out some examples like: HubSpot's marketing blog or iGoMoon's blog. I'm trying to figure out where I should start. Should I begin with the first line of code? Or can I import sample code ...

Decoding a solitary element within an array

How can I unmarshal JSON arrays into single objects in Go? For instance, consider a JSON response retrieved from an API endpoint: { "results": [ { "key": "value" } ] } In my Go code, I have defined a struct to represent the object in ...

What is the best way to get rid of a connect-flash notification?

I'm having trouble removing the message (with the username displayed) after logging out by pressing the logout button. Every time I try to press the logout button, it just refreshes the page without any action. I want to stay on the same page and not ...

Japanese Character File Naming Convention

When dealing with certain Japanese characters, the content disposition header appears as follows: Content-Disposition: attachment; filename=CSV_____1-___.csv; filename*=UTF-8''CSV%E3%82%A8%E3%83%93%E3%83%87%E3%83%B3%E3%82%B91-%E3%82%B3%E3%83%94%E ...

React - Why does React fail to update the state when expected? (not retaining)

Hello there, I'm currently working on fetching JSON data from an API and populating it into a table. It seems pretty straightforward but here's where things get tricky – I can see that the "tableData" state is getting updated as new rows are ad ...

I'm having trouble getting my jsonp to function properly. Can anyone help me troubleshoot?

I've been working on my website for the past two weeks, learning HTML, CSS, and a bit of JavaScript. However, I'm facing an issue with the following code that I can't seem to resolve: <head> <script src="http://ajax.googleapis.com/ ...

`Issues with AJAX PHP file upload`

I've been working on an AJAX PHP upload script, but I'm facing some issues. Once the user selects an image to upload, it should display in the specific div container specified in my javascript file (which is working fine). However, I believe ther ...

React Modals: Only the modal component triggered by the first click will open, with no other modals opening

As a newcomer to StackOverflow, I apologize if my problem description is not clear. I am currently learning React and working on a course-search app as a project. The app filters courses based on user input from a JSON file and displays them in cards with ...

What is the best way to eliminate the "0"s from the center of items within an array?

I have developed a table sorter that handles columns containing both letters and numbers, such as "thing 027". To facilitate sorting, I prepended zeros to the numbers. However, I am now looking for a cleaner way to remove these zeros from the numbers using ...

Adding Bootstrap component via ajax request

I'm facing an issue with injecting a Bootstrap component using ajax. I usually include a select element like this: <select class="selectpicker" data-width="75%"> Most of the HTML code is generated dynamically through javascript, which you can ...

When attempting to showcase array information in React, there seems to be an issue with the output

After printing console.log(response.data), the following output is displayed in the console. https://i.sstatic.net/LLmDG.png A hook was created as follows: const [result,setResult] = useState([]); The API output was then assigned to the hook with: setRe ...