1

I am new to using the Plotly library and this time I find myself with the need to show in Vuejs 2 a circular progress graph like the following one.

circular pogress chart

I know that plotly is very complete but I have not seen an example with a similar aspect and that is also with javascript.

Thanks in advance for any information or help you can provide.

Greetings!

With plotly Derek Example, the graph looks like this

plotly code by Derek example

My English is not very good, but note that the line of the circle does not have a smooth curvature.

Derek O
  • 16,770
  • 4
  • 24
  • 43
  • I don't think such a chart exists in `plotly.js`: you would need to construct it yourself using shapes and annotations. i can create an example to replicate your chart if you're interested – Derek O Dec 08 '21 at 02:32

1 Answers1

0

You can use plotly.js traces and text to recreate the components of this chart. If you use a scatter to place down an array of markers, you can create the grey arc, then place the red arc over it. To calculate the coordinates of each these markers, you can center your axes at (0,0) then use x=r*cos(theta) and y=r*sin(theta) where theta is your angle in radians. You can get an array of x and y values to trace out the desired portions of the red and grey arcs.

To get the circular chart to look like yours, I set the range of the x-axes and y-axes both to [-2,2], made the radius of the circular arcs 0.9 with [0,0] as the center, set the markers for these arcs to be size 10, and made the grey arc go from 210 to 85 degrees and red arc go from 90 to -200 degrees (using the function makeArr written by mhodges in his answer here),. Then to get the green marker to display in the legend, I created a trace with a green marker but with null values so it doesn't plot anything on the chart. Text traces can be used to add text around the center of the circular arcs.

Here is an example (codepen is here):

// credit goes to mhodges: https://stackoverflow.com/a/40475362/5327068
function makeArr(startValue, stopValue, cardinality) {
  var arr = [];
  var step = (stopValue - startValue) / (cardinality - 1);
  for (var i = 0; i < cardinality; i++) {
    arr.push(startValue + (step * i));
  }
  return arr;
}

// The function returns two arrays of circle coordinates
// for the outer points of a circle centered at some (x,y)
// and with a radius r with an arc of theta values
function getCircleCoords(r, center, degree_values) {
  var center_x=center[0]
  var center_y=center[1]
  var x_coords = []
  var y_coords = []
  for (var i = 0; i < degree_values.length; i++) {
    x_coords.push(center_x + (r * Math.cos(degree_values[i]*Math.PI/180)));
    y_coords.push(center_y + (r * Math.sin(degree_values[i]*Math.PI/180)));
  }
  return [x_coords,y_coords]
}

var trace1 = {
  x: [0],
  y: [0.15],
  text: ['1000'],
  mode: 'text',
  textfont: {
    family: 'arial',
    size: 28,
    color: 'black'
  },
  showlegend: false
};

var trace2 = {
  x: [0],
  y: [-0.15],
  text: ['kW/kg'],
  mode: 'text',
  textfont: {
    family: 'arial',
    size: 22,
    color: 'grey'
  },
  showlegend: false
};

circleCoords = getCircleCoords(r=0.9, center=[0,0], radian_values=makeArr(90,-200,1000))
backgroundCircleCoords = getCircleCoords(r=0.9, center=[0,0], radian_values=makeArr(210,85,1000))

// display a marker in the legend without plotting it
var trace3 = {
  x: [null],
  y: [null],
  mode: 'markers',
  marker: {color: 'green', size: 10},
  name: 'Correcto funcionamiento'
};

// grey background circle
var trace4 = {
  x: backgroundCircleCoords[0],
  y: backgroundCircleCoords[1],
  mode: 'markers',
  marker: {color: '#eeeeee', size: 10},
  name: null,
  showlegend: false
};

// red foreground circle
var trace5 = {
  x: circleCoords[0],
  y: circleCoords[1],
  mode: 'markers',
  marker: {color: 'red', size: 10},
  name: 'Funcionamiento erroneo'
};

var layout = {
  title:'Relacíon potencia peso',
  xaxis: {
    range: [-2, 2],
    zeroline: false,
    showgrid: false,
    zeroline: false,
    showline: false,
    showticklabels: false
  },
  yaxis: {
    range: [-2, 2],
    showgrid: false,
    zeroline: false,
    showline: false,
    showticklabels: false
  },
  width: 600,
  height: 600,
  legend: {
    x: 0,
    y: 0,
    "orientation": "h"
  }
};

var data = [trace1, trace2, trace3, trace4, trace5];
Plotly.newPlot('myDiv', data, layout);

enter image description here

EDIT: for a smoother circle, you can increase the number of markers used to draw the circle.

circleCoords = getCircleCoords(r=0.9, center=[0,0], radian_values=makeArr(90,-200,5000))
backgroundCircleCoords = getCircleCoords(r=0.9, center=[0,0], radian_values=makeArr(210,85,5000))
Derek O
  • 16,770
  • 4
  • 24
  • 43
  • Thank you! It has worked, the only thing I would like is for the circle to be a little more uniform, it looks like a very square approach, but it shows what I need. – Luis G. Luna B. Dec 09 '21 at 09:59
  • I am a bit confused what you mean by you want the circle to be more uniform - i'd be happy to update my answer if you could explain a bit further. for now, if my answer helped, then please consider [accepting it](https://stackoverflow.com/help/someone-answers) - thank you! – Derek O Dec 09 '21 at 15:42
  • Hello Derek, what I mean is that after implementing the code that you indicated, the line of the circle looks a bit square, do you understand me? My English is not very good. What I would love is that the line of the circle is "smooth" or is not square hehe – Luis G. Luna B. Dec 11 '21 at 15:42
  • @LuisG.LunaB. I have trouble understanding what you mean when you say "the line of the circle looks a bit square". Could you update the image in your question to show the desired chart? That could help clear things up – Derek O Dec 11 '21 at 19:17
  • Hi Derek, how are you? I have updated my post with the image from the plotly chart – Luis G. Luna B. Dec 15 '21 at 08:40
  • Oh I see what you mean! It's not perfect smooth because this chart is being drawn using 1000 markers. If you increase the number of markers, the result should look better. – Derek O Dec 15 '21 at 14:38