Switch up the sequence of selected/appended SVGs in D3

In this dot matrix visual example, different colored circles represent funding percentages from three countries: USA, Canada, and Mexico. The gray circles indicate the remaining funding to be raised. The code snippet showcases how the circles are mapped based on the funding values.

var margins = {top:20, bottom:300, left:30, right:100};

var height = 600;
var width = 900;

var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;

var svg = d3.select('body')
    .append('svg')
    .attr('width', totalWidth)
    .attr('height', totalHeight);

var graphGroup = svg.append('g')
    .attr('transform', "translate("+margins.left+","+margins.top+")");

var data = [
  {'country':'USA', 'value':.20},
  {'country':'Canada', 'value':.15},
  {'country':'Mexico', 'value':.10}
];

var circArray = new Array(50);
var circPercentage = 100/circArray.length;

var circData = new Array;

data.forEach(function(item) {

  for (var i =0; i <item.value*100/circPercentage; i++) {
    circData.push(item.country);
}
});
var arrayDiff = 50-circData.length;
for (var i=0; i <(arrayDiff); i++) {
  circData.push("");
}

//console.log(circData)

var maxColumn = 10;

var colorMap = {
  'USA':"#f6d18b",
  'Canada':"#366092",
  'Mexico':"#95b3d7",
  "":"#a6a6a6"
};

var xScale = d3.scaleLinear()
    .range([0,width])
    .domain([0,1]);

var yScale = d3.scaleLinear()
    .range([height,0])
    .domain([0,1]);


graphGroup.selectAll('circle')
    .data(circData)
    .enter()
    .append('circle')
    .attr('cx', function(d, i) {
        return (i % maxColumn) * 30
    })
    .attr('cy', function(d, i) {
        return ~~((i / maxColumn) % maxColumn) * 30
    })
    .attr('r', 10)
    .style('fill', function(d) {
      //console.log(d)
      return colorMap[d];
    });
<script src="https://d3js.org/d3.v5.min.js"></script>

Although the circles are currently mapped in a specific order, the concern arises when considering other layout options, such as having the gray circles on top or on the left. The question is whether there is a straightforward way to toggle the direction of the SVG elements, or if transposing the data itself is the only solution.

Question

Is there a more sophisticated method to change the order of the SVG elements, without having to reorganize the data structure itself? Any insights on this would be greatly appreciated.

Answer №1

In the code, the order corresponds to the circData array.

However, it is the cx and cy values that actually determine the position, not their sequence in the array.


var margins = {top:20, bottom:300, left:30, right:100};

var height = 600;
var width = 900;

var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;

var svg = d3.select('body')
    .append('svg')
    .attr('width', totalWidth)
    .attr('height', totalHeight);

var graphGroup = svg.append('g')
    .attr('transform', "translate("+margins.left+","+margins.top+")");

var data = [
  {'country':'USA', 'value':.20},
  {'country':'Canada', 'value':.15},
  {'country':'Mexico', 'value':.10}
];

var circArray = new Array(50);
var circPercentage = 100/circArray.length;

var circData = new Array;

data.forEach(function(item) {

  for (var i =0; i <item.value*100/circPercentage; i++) {
    circData.push(item.country);
}
});
var arrayDiff = 50-circData.length;
for (var i=0; i <(arrayDiff); i++) {
  circData.push("");
}

circData.reverse() //<---------------------------

//console.log(circData)

var maxColumn = 10;

var colorMap = {
  'USA':"#f6d18b",
  'Canada':"#366092",
  'Mexico':"#95b3d7",
  "":"#a6a6a6"
};

var xScale = d3.scaleLinear()
    .range([0,width])
    .domain([0,1]);

var yScale = d3.scaleLinear()
    .range([height,0])
    .domain([0,1]);


graphGroup.selectAll('circle')
    .data(circData)
    .enter()
    .append('circle')
    .attr('cx', function(d, i) {
        return (i % maxColumn) * 30
    })
    .attr('cy', function(d, i) {
        return ~~((i / maxColumn) % maxColumn) * 30
    })
    .attr('r', 10)
    .style('fill', function(d) {
      //console.log(d)
      return colorMap[d];
    });
<script src="https://d3js.org/d3.v5.min.js"></script>

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

Accessing store state in axios plugin with Nuxt.js

I've encountered a problem where I have a token stored, but I'm struggling to access it in my axios plugin while using Nuxt.js. In the past with just Vue, it was simple to import the store and access the token. However, I'm having difficulty ...

The Echart bar graph is not displaying when trying to use JSON data

Seeking assistance as a beginner in building Basic Bar inverted axes using json data. I am trying to achieve a chart similar to Bar Inverted Axes, but encountering issues with the chart not displaying properly. Utilizing Angular to develop the web applicat ...

Exploring MongoDB through User Interface Requests

As part of a project to develop a minimalist browser-based GUI for MongoDB, an interesting question has arisen. How can we accurately display the current state of the database and ensure it is continuously updated? Specifically, what methods can be utiliz ...

The PHP equivalent of converting data to a JSON string, similar to the

When working with PHP's json_encode($array), I've noticed that diacritics can sometimes get messed up. However, if I update my database column to type text and pass javascript-created JSON over HTTP, everything appears fine. The issue arises when ...

Utilizing JQuery to recycle data post-load

I've got this function: // AJAX MESSAGES DISPLAYING show_msg.on('click', function(e){ var $this = $(this), url = $this.attr('href'), url_info = url + ' .basic_info > *', url_msg = url + ' .cont ...

Is there a way to merge all this data into a single Object?

This particular situation is quite complex. Let's consider the following scenario: I have two JavaScript objects that are fetched via REST calls, using two different callbacks. So, we have: call1() - POST method - parsed JSON to JavaScript object, ...

Using JQuery to make POST requests is successful, however, utilizing the XMLHttpRequest object to make

Currently, I am attempting to make a POST request from Javascript to my server in PHP but without utilizing jQuery. The following code successfully sends the required data to the database: var msg = {}; msg['name'] = 'joe'; msg['m ...

Retrieving information from a JSON file and dynamically displaying it on an HTML page using JavaScript

I've been working on pulling data from a JSON file to display on my website. Following this helpful guide at: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON, but unfortunately, I'm facing an issue where nothing is showing ...

"Trouble arises when event listener fails to function following an append operation

Recently, I delved into the world of HTML/CSS and jQuery in an attempt to create a simple web game. Below is a snippet of my HTML code: function playGame() { var theLine = "<div id = \"line\">"; for (var i = 0; i < 9; ...

What is the best approach to unit testing this React Component?

I have created a component that acts as a wrapper for another component. My question is, how should I approach unit testing for this component? Besides checking the state and method calls to ensure they update the state correctly. Other than rendering pro ...

Submit information from an HTML form to a PHP script and then send the response back to the client using AJAX,

Looking to run a PHP script using AJAX or JavaScript from an HTML form and then receive the results on the HTML page. This is what my changepsw.php file looks like: <?php // PHP script for changing a password via the API. $system = $_POST['syst ...

Ways to trigger an npm script from a higher-level directory?

After separately creating an express-based backend (in folder A) and a react-based front-end project (in folder B), I decided to merge them, placing the front-end project inside the back-end project for several advantages: No longer do I need to manu ...

What is the best way to adjust the size of the circles in my d3 leaflet implementation based on the frequency of longitude/latitude pairs?

I'm currently diving into the world of d3 and attempting to create a map using leaflet. Within my dataset, I have thousands of latitude and longitude coordinates. While I've successfully plotted circles on a leaflet map in d3, I'm now faced ...

Styling with CSS and JavaScript: The ultimate method for desaturating multiple images

I am currently designing a portfolio website that will feature desaturated thumbnails of all my work. When you hover over each thumbnail, the color will fade in and out upon mouseover. Since this page will include numerous thumbnails, I have been contempl ...

Unable to Update the Status Code

When it comes to setting the status code to 9999, I am utilizing the basic Response.StatusCode. In this case, the page is accessed via an AJAX call and the status code is checked at readyState = 4. On detecting 9999 as the status code, an alert pops up wit ...

vuejs function for modifying an existing note

Method for editing an existing note with Vue.js in a web application This particular application enables users to perform the following tasks: Create a new note View a list of all created notes Edit an existing note Delete an existing note Prog ...

How can I take photos in bulk when I open the camera on Ionic 3?

Is there a way to capture multiple images at once using the camera? Currently, I am only able to capture one image when the user clicks. However, I would like to capture four images when the user clicks the success button. let options: CaptureImageOption ...

Tips for incorporating a download button into a video player using Plyr JS

I'm using Plyr JS and I am trying to add a download option for each video. Here is what I've done so far to make the download option work: Even though I have included: controlsList="nodownload" <video controls crossorigin playsinline contro ...

Reloading a page will display [object CSSStyleDeclaration]

Upon editing content and saving changes, instead of displaying my updated content when refreshing the page, it shows [object CSSStyleDeclaration]. function newElement() { let li = document.createElement("li"); let inputvalue = document.querySelector ...

Is there a way to effectively alter an object that has been assigned in a separate file?

Seeking Assistance: I am facing an issue in my current project where I need to store a javascript object in an external file and then export it using module.exports. The challenge now is that I want another file to be able to modify a specific value withi ...