"Switching between old and new plots in D3: A step-by-step guide on transitioning plots using the menu

I'm in the process of transitioning from one plot to another by changing the menu options. My menu now includes a new column (feature: y axis) extracted from the dataset, and my goal is to redraw the plot with new dots on the x/y axis. However, I've encountered an issue where my code doesn't remove the previous plot but continues adding additional plots below the old one. How can I modify the code below to smoothly transition the plot with a delay instead of continually adding new plots?

Thank you,

var cValue = function(d) { return d[cVar];},
color = d3.scale.category10();

// initialize tooltip area on the webpage
var tooltip = d3.select("body").append("div")
            .attr("class", "tooltip")
            .style("opacity", 0);


// update data when menu option is changed    
var menu = d3.select("#menu select")
    .on("change", change);

// load data
d3.csv("sample_data.csv", function(error, data) {
  formatted = data;
  redraw();
});


d3.select(window)
    .on("keydown", function() { altKey = d3.event.altKey; })
    .on("keyup", function() { altKey = false; });
var altKey;


// define transition behavior for when a new indicator is selected   
function change() {
  d3.transition()
      .duration(altKey ? 7500 : 1500)
      .each(redraw);
}

function redraw() {
  // setup x 
  var xValue = function(d) { return d[xVar];}, // data -> value
      xScale = d3.scale.ordinal()
                 .rangeRoundBands([0,width],1),  //value -> display
      xMap = function(d) { return (xScale(xValue(d)) + Math.random()*10);},   // data -> display
      xAxis = d3.svg.axis().scale(xScale).orient("bottom");

   // setup y
   var yVar = menu.property("value"),
      yValue = function(d) { return d[yVar];}, // data -> value
      yMap = function(d) { return yScale(yValue(d));}, // data -> display
      yScale = d3.scale.linear().range([height, 0]), // value -> display
      yAxis = d3.svg.axis().scale(yScale).orient("left");

  data = formatted.filter(function(d, i) 
  { 
          if (d[cVar] == Prod) 
          { 
              //console.log(d);
              return d; 
          } 
  });

  // convert string values into numbers
  data.forEach(function(d) {
    d[xVar] = d[xVar];
    d[yVar] = +d[yVar];
  });

   xScale.domain(data.sort(function(a, b) { return d3.ascending(a[xVar], b[xVar])})
                .map(xValue) );

  yScale.domain([d3.min(data, yValue)-1, d3.max(data, yValue)+1]);

  var svg = d3.select("body").append("svg")
              .attr("width", width + margin.left + margin.right)
              .attr("height", height + margin.top + margin.bottom)
              .append("g")
              .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  // x-axis
  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis)
    .append("text")
      .attr("class", "label")
      .attr("x", width)
      .attr("y", -6)
      .style("text-anchor", "end")
      .text(xVar);

  // y-axis
  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("class", "label")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text(yVar);

  // draw dots
  svg.selectAll(".dot")
      .data(data)
      .enter().append("circle")
      .attr("class", "dot")
      .attr("r", radius)
      .attr("cx", xMap)
      .attr("cy", yMap)
      .style("fill", function(d) { return color(cValue(d));}) 
      .on("mouseover", function(d) {
          tooltip.transition()
               .duration(200)
               .style("opacity", .9);
          tooltip.html(d[SN] + "<br/> (" + xValue(d) 
          + ", " + yValue(d) + ")")
               .style("left", (d3.event.pageX + 5) + "px")
               .style("top", (d3.event.pageY - 28) + "px");
      })
      .on("mouseout", function(d) {
           tooltip.transition()
               .duration(500)
               .style("opacity", 0);
      });
};    

Answer №1

After some exploration, I managed to figure out a solution on my own. By implementing "svg.remove()" during each menu selection call and then invoking "draw()", I am able to refresh the svg element. However, this approach leads to redrawing the entire plot, including x-axis, y-axis, legend, and dots. While not ideal, it serves as a temporary workaround that allows me to continue making progress.

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

What strategies can be used to efficiently perform Asynchronous Operations on a high volume of rows in a particular database table?

I am looking to perform Asynchronous Operations on every row of a specific database table, which could potentially contain 500,000, 600,000, or even more rows. My initial approach was: router.get('/users', async (req, res) => { const users = ...

Enhance the appearance of your custom three.js Geometry by incorporating different textures

I have been struggling to implement UV-mapping on my custom geometry in three.js. Despite trying various solutions, none seem to be working. Can someone provide a clear explanation of how UV-mapping functions and the correct way to implement it? var s = 1 ...

Showcasing a component for a seven-day period with the power of Javascript

Here is my current JavaScript code: var today = new Date(), d = today.getDate(), m = today.getMonth() + 1, y = today.getFullYear(), date = d + '/' + m + '/' + y, specialDate = '22/10/2012'; if (date == specialDate) { documen ...

When a single object is entered, JSON returns 'undefined', however, it works successfully when using the .map() function

Utilizing Axios to fetch data from DeezerAPI, I initially rendered information using .map() and everything worked smoothly when passing it to a Component. However, when attempting to access a single JSON object, I encountered an 'undefined' error ...

Creating a dynamic select functionality in Drupal forms

Being more focused on backend development, I am facing a challenge that may be simple for jQuery experts. In Drupal, I have two arrays - one containing names of views and the other having displays for each view. To populate these arrays, here is the code s ...

"Exploring Angular: A guide to scrolling to the bottom of a page with

I am trying to implement a scroll function that goes all the way to the bottom of a specific section within a div. I have attempted using scrollIntoView, but it only scrolls halfway down the page instead of to the designated section. .ts file @ViewChild(" ...

When accessing WordPress through a URL, I am able to view regular PHP files but encounter difficulty accessing any uploaded files

Currently working on a Wordpress project and facing issues with creating a product via the WooCommerce REST API. I managed to make it work in my local environment, but upon uploading the files to the server, I am unable to reach a specific file via URL. Fo ...

Tracking modifications in a text document using ajax (javascript)

After conducting extensive research, I have yet to find a solution that addresses the issue at hand. My current webpage features a text input field that triggers a function whenever its contents are changed, resulting in data being written to a text file. ...

The ID value did not pick up the number 0 when passed to the next blade after the initial reading

When passing an ID value to another blade file, I encountered an issue where the other blade file did not read the number 0 at the beginning. For example, if I pass the value of 006, when I console log the value in the other blade view, it only shows 6. H ...

Encountering the error "Cannot GET /login" while attempting to send a file through a post request in Express.js

I'm having trouble sending a new HTML file to the user after a successful login. Every time I attempt to send the file, I keep getting an error message saying "Cannot GET /login" on the page. Below is the section of code that's causing me diffic ...

A helpful guide on using workbox to effectively cache all URLs that follow the /page/id pattern, where id is a

Looking at this code snippet from my nodejs server: router.get('/page/:id', async function (req, res, next) { var id = req.params.id; if ( typeof req.params.id === "number"){id = parseInt(id);} res.render('page.ejs' , { vara:a , va ...

What would be the benefit of separating the express and app components?

Every time I look at an Express app, these two lines catch my eye. const express = require('express'); const app = express(); I always wonder if any parameters can be passed to express(). After checking here, I didn't find any. https://e ...

Creating a dynamic table based on selected dropdown option

I need to create a dynamic table of questions depending on the user's selection from a dropdown menu. When the user chooses a category, I want to pass that information to an API using the GET method. My controller is built using AngularJS. However, I ...

Struggling to align my image in the center while applying a hover effect using CSS

Hey there, I'm having an issue centering my image when I add instructions for it to tilt on mouseover. If I take out the 'tilt pic' div, the image centers just fine. Can anyone help me identify what I might be doing wrong? Thanks in advance! ...

Iterating through each data attribute using a jQuery each loop

I've encountered an issue with resetting data attributes post-animation and have been attempting to implement a method found on answer 2 of a related thread. I'm a bit stuck on what might be causing the problem. It should theoretically be possib ...

What are some ways to include additional data besides the new value in a change event for an input field?

Currently, I am using VueJS to dynamically generate a form based on a JSON schema and then attempting to save the data into my Vuex state. Here is an overview of the code I have written so far (simplified): <div v-for="field in schema" :key=& ...

The linking process in AngularJS is encountering difficulties when trying to interact with

I've already looked at similar questions, and my code seems correct based on the answers provided. It's a very simple beginner code. <html ng-app=""> <head> <title>Assignment</title> <script src=" ...

What is the best way to deliver an HTML document in Express from a directory that is one level higher than my server folder?

I am facing an issue while trying to access an HTML file from my main directory through my Express server, which is located one level deeper in the server folder. Below is the configuration of my server code: const express = require('express') ...

Select a filter first before uploading your image

Here I have a script that allows users to select a folder. My question is how can I modify the script so that once they have chosen a folder, the script will send the picture to a PHP script for uploading to the server? $(function() { /* Th ...

The Vue v-model-bound HTML element is unable to update the Vue instance when a different JavaScript entity binds to it and modifies the data

In my project, I have implemented Vue.js for two-way data binding on a remote control alarm clock. The main code can be found here. You can access the running instance of the server here. While most of the page uses Vue and JavaScript for rendering, I de ...