Utilizing Javascript and D3 to create visually stunning Radar Graphs

I'm brand new to using Javascript and I've hit a roadblock while trying to construct a Radar/Web graph for my current project.

The graph in question is a three-point Radar Graph that measures Base Attack, Defense, and Stamina. My goal is to overlay a triangle (or another polygon) on top of these points to create a clear "radar" shape:

.

This data is being fetched through an API and is displayed using SQLite. The API requires a specific ID number to fetch the corresponding Base Statistics.

Below is the code snippet responsible for generating the graph:

function getBaseStats(pokecharID) {
  var queryUrl = "/api/v1/base_stats";
  var int_pokeCharID = parseInt(pokecharID);

  let filteredStats = [];
  let statsList = [];
  statsList.length = 0;



 d3.json(queryUrl).then((data) => {
    filteredStats.push(
      data.filter((stat) => stat[0] === int_pokeCharID && stat[1] === "Normal")
    );

var base_attack = filteredStats[0][0][2];
var base_defense = filteredStats[0][0][3];
var base_stamina = filteredStats[0][0][4];

var w = 500,
  h = 500;

var colorscale = d3.scaleOrdinal(d3.schemeCategory10);

var d = [
  [
    { axis: "Base Attack", value: base_attack },
    { axis: "Base Defense", value: base_defense },
    { axis: "Base Stamina", value: base_stamina },
  ],
];

I truly appreciate any guidance provided!

Edit: Included code attempting to create polygon.

    var area = d3.svg.area.radial()
.interpolate("cardinal-closed")
.angle(function(d) { return angle(d.time); })
.innerRadius(function(d) { return radius(d.y0); })
.outerRadius(function(d) { return radius(d.y0 + d.y); });

Answer №1

Here is an illustrative example with various adjustments to meet your specific criteria:

const data = [
  {shade: 'red', quantities: [500, 400, 900]},
  {shade: 'purple', quantities: [800, 200, 400]},
  {shade: 'yellow', quantities: [300, 1000, 600]},
];

const svgCanvas = d3.select('svg');

const maxValue = 1000;
const radiusSize = 150;
const centerPoint = {x: 250, y: 200};

const radialScale = d3.scaleLinear()
  .domain([0, maxValue]) 
  .range([radiusSize, 0]) 
  
const axis = d3.axisRight()
    .scale(radialScale)
    .ticks(5)

svgCanvas.append('g')
  .attr('transform', `translate(${centerPoint.x},${centerPoint.y - radiusSize})`)
  .call(axis);

let value, angle;
for (value = 0; value <= maxValue; value += maxValue / 5) {
  const r = radialScale(value);
  svgCanvas.append('circle')
    .attr('cx', centerPoint.x)
    .attr('cy', centerPoint.y)
    .attr('r', r)
    .style('stroke', '#aaa')
    .style('fill', 'none');
}

const labelsArr = ['Attack Power', 'Stamina Level', 'Defensive Strategy'];
const alignTo = ['middle', 'start', 'end'];
const shifting = [{x: 0, y: -15}, {x: 10, y: 15}, {x: -10, y: 15}];

for (let idx = 0; idx < labelsArr.length; idx++) {
  const angle = idx * Math.PI * 2 / labelsArr.length;
  const xCoord = centerPoint.x + radiusSize * Math.sin(angle);
  const yCoord = centerPoint.y + radiusSize * -Math.cos(angle);
  if (angle > 0) {
    svgCanvas.append('line')
        .attr('x1', centerPoint.x)
        .attr('y1', centerPoint.y)
        .attr('x2', xCoord)
        .attr('y2', yCoord)
        .style('stroke', '#000');
  }
  svgCanvas.append('text')
    .text(labelsArr[idx])
    .attr('text-anchor', alignTo[idx])
    .attr('dx', shifting[idx].x)
    .attr('dy', shifting[idx].y)
    .attr('x', xCoord)
    .attr('y', yCoord)
}

data.forEach(({shade, quantities}, idx) => {
    let pathString = '';
  for (let i = 0; i < quantities.length; i++) {
    const r = radiusSize - radialScale(quantities[i]);
    console.log('V: ', quantities[i]);
    console.log('R: ', r);
    const angle = i * Math.PI * 2 / quantities.length;
    const x = centerPoint.x + r * Math.sin(angle);
    const y = centerPoint.y + r * -Math.cos(angle);
    pathString += `${i > 0 ? 'L' : 'M'} ${x},${y} `;
  }
  pathString += 'Z';
  svgCanvas.append('path')
    .attr('d', pathString)
    .style('stroke', shade)
    .style('stroke-width', 3)
    .style('stroke-opacity', 0.6)
    .style('fill', shade)
    .style('fill-opacity', 0.3)
  
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg width="500" height="400">
  
</svg>

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

The necessary text field is being marked in red prior to form submission

While developing a web app using React/Bootstrap, I encountered a bug where the required textarea is highlighted in red as soon as the form is opened, before clicking submit. You can view the issue in this Imgur album (first picture shows the form opened, ...

Utilizing Bootstrap, Jquery, and Node.js for web development

I am seeking clarification on the process for running these two commands: npm install jquery npm install boostrap After adding the dependencies to my package.json file, I then include them in my app.js file using the code: var $ = require('jquery&a ...

Is it possible to use Node.js child processes without carriage returns?

My Node.js script is set up to handle some database operations by creating child processes using the spawn functionality. However, I encountered a strange issue where the output stopped displaying carriage returns. Here's an example of what was happen ...

Protractor end-to-end tests: extracting chosen menu item from page model function

My website has a navigation menu with different items. I'm using a page model for end-to-end tests. In one of my test specs, I need to call a function from the page model that does the following: Check that only one item in the menu has a specific ...

Determining Cookies with Jquery Function and Directing Attention

In my asp.net website, I have configured the login control to remember the username using cookies. Is there a way to utilize a JQuery (JavaScript) function to check for the presence of cookies and automatically shift focus to the password field? ...

Encountering errors while testing a NUXT.js and Vue.js application using Jest, specifically seeing messages like '[vuex] module namespace not found in mapState()' and '[vuex] unknown action type'

Despite NUXT's automatic namespacing feature, I am encountering difficulties testing or referencing the store in my testing modules. Can anyone offer advice on how to edit the namespacing property in a Nuxt app? Below is the code for the component, s ...

Prevent button interaction until completion of modal animation using Bootstrap 4

I have incorporated a Bootstrap 4 modal in my website to display a large navigation menu. The navigation is triggered by a toggle button with a CSS animation that transforms a hamburger icon into an X. However, I encountered an issue where if the button i ...

Execute the task from an external JavaScript file using npm

Utilizing node and npm as a task runner from gitbash cli has been successful for the most part. However, I am facing an issue where I am unable to call tasks in separate .js files from my package.json. Any assistance with the syntax would be greatly apprec ...

"Unlocking the JSON element with jQuery Ajax: A step-by-step guide

I am trying to pinpoint a specific element within my JSON data: { "taskMeta": "Some meta info", "tasksLib": [ { "task001": { "id":"1", "createDate":"01.02.17", "dueDate":"02.03.17", "au ...

"Enhance Your Text Fields with Angular2 Text Masks for Added Text Formatting

Is there a way to combine text and numbers in my mask? This is what I am currently using: [/\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/] The above code only allows for numbers. How can I modify it to allow f ...

Refresh a radio question to maintain the value using a BehaviorSubject

I am currently working with Angular 7 to create a form that includes a radio button question asking if an event occurred in a specific country. My goal is to retain the selected value even if the user navigates away and returns to the form. questions.serv ...

Showcasing articles in an XML feed according to specific keywords found in the headline

I'm currently working on designing a website for a client and I want to minimize my involvement in its maintenance. I am considering using RSS feeds to automate the process by having content posted on Blogger and then feeding it to the site. However, ...

Create a mechanism in the API to ensure that only positive values greater than or equal to 0 are accepted

My goal is to process the API result and filter out any values less than 0. I've attempted to implement this feature, but so far without success: private handleChart(data: Object): void { const series = []; for (const [key, value] of Object.e ...

What Causes My Issue with $(document).ready()?

Currently delving into the world of jQuery, but I've hit a roadblock. Below is the snippet in question: var script = document.createElement('script'); script.src = 'https://code.jquery.com/jquery-3.4.1.min.js'; script.type = " ...

Perform a series of tasks concurrently within a function using Grunt

I am currently utilizing grunt-shell along with other custom tasks in my project. In one of my tasks, I need to execute these tasks sequentially and verify the output of each task. Here is a simplified representation: grunt.task.registerTask('test&ap ...

What is the correct way to show a JavaScript response on the screen?

Here is the JavaScript code I used to call the server API: <script type='text/javascript'> call_juvlon_api(apikey, 'getAvailableCredits', '', function(response) { document.getElementById('show').innerHT ...

How is it possible for my search results page to retrieve the words I input?

Currently, I am in the process of creating the search result page and I plan to utilize dynamic routing for implementation. Here is a snippet of my search bar code: <Link href={`/productSearchResult/${searchWord}`}> <a className={styles.navbar_s ...

utilizing AJAX to retrieve scripts from WITHIN my own domain

In the realm of ajax scripts, I encounter a scenario where referencing something within the same domain requires passing HTML and associated javascript. Due to it being a non X-domain setup, I anticipate that this could be achievable. The aim here is to fe ...

Tips for accessing data from a local JSON file in your React JS + Typescript application

I'm currently attempting to read a local JSON file within a ReactJS + Typescript office add-in app. To achieve this, I created a typings.d.ts file in the src directory with the following content. declare module "*.json" { const value: any; ex ...

Switch to using addresses instead of latitude and longitude coordinates when utilizing the Google Maps API

I am looking to utilize Google Map Markers to indicate the locations where our services are offered. The code I have created using latitude and longitude is functioning properly, however, for my project I need to display city names instead of lat/long ...