Radial Gradient, for plot bands on a gauge? - javascript

Alrighty so I've run into an interesting little problem. I am trying to create a gauge chart, which then has plot bands. Simple enough.
The complication comes in when I want the plot bands to have a gradient run through the center of if evenly.
A rough js fiddle I forked:
http://jsfiddle.net/maraket/omez0n9r/3/
It should be noticed I am trying a radialgradient with a sharp change as per:
{
color: {
radialGradient: {
cx: 0.5,
cy: 0.5,
r: 0.5
},
stops: [
[0, '#000000'],
[0.8, '#ffffff'],
[1, '#000000'],
]
},
from: 0,
to: 100,
innerRadius: '90%',
outerRadius: '110%'
}
Now for a single plotband I noticed that the radial Gradient is more eliptical then circular which makes the solution I'm using not ideal. Furthermore when using multiple plotbands this solution won't work, since it uses the local plotbands x,y which changes if there are multiple plot bands. Any thoughts would be very helpful.

The reason why gradient is elliptical is because the bounding box of the plot band is not a square, but more a rectangle. It is because, you don't use full angle. Compare the gradient with full angle pane - http://jsfiddle.net/3mm1bjqf/.
Because your bounding box is not a square, then you need to define your own coordinate system for the gradient. Gradient attributes can be obtained from axis properties.
Your gradient should look like this:
plotBands: [{
color: {
radialGradient: {
gradientUnits: 'userSpaceOnUse', // we use our own coord system instead of bbox
cx: axis.left + axis.center[0],
cy: axis.top + axis.center[1],
r: axis.center[2] / 2 * 1.1 // multiplying by 1.1 because plotBand's outerRadius is set to 110%
},
Unfortunately, this gradient must be set dynamically because you do not know axis coords before the chart is rendered - so it must be done on load/redraw events.
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'gauge',
events: {
load: function() {
var axis = this.yAxis[0];
axis.update({
plotBands: [{
color: {
radialGradient: {
gradientUnits: 'userSpaceOnUse',
cx: axis.left + axis.center[0],
cy: axis.top + axis.center[1],
r: axis.center[2] / 2 * 1.1
},
stops: [
[0, '#000000'],
[0.8, '#ffffff'],
[1, '#000000'],
]
},
from: 0,
to: 100,
innerRadius: '90%',
outerRadius: '110%'
}]
})
}
}
},
example: http://jsfiddle.net/zfyzvqw1/

Related

How show a circular progress chart with Plotly Javascript

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.
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
My English is not very good, but note that the line of the circle does not have a smooth curvature.
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);
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))

How to render custom line with echarts?

Been struggling to find this, and have even resorted to logging output of echarts' various objects in the console to try to see what's going on. It would seem that visualMap doesn't work properly when you specify a different dimension in your data, so I've been trying to write a simple renderItem function for my line series. I can't find any documentation or examples on specifics for rendering a line - specifically, when data is passed into it, how do I get coordinate points for both the start and end of the line? I can get the values of the point (the data point which would give you the coordinates of the current data point), but a line consists of 2 points (start and end). What am I missing here?
Codepen example to play with: https://codepen.io/WorldWideWebb/pen/JjbJpRJ
visualMap that didn't work (it changes the color of the point, NOT the line; the point colors do change just fine, but I want to color the line)
visualMap: {
dimension: 3,
seriesIndex: 2,
show: false,
pieces: [{
gt: 0,
lte: 50,
color: '#93CE07'
}, {
gt: 50,
lte: 100,
color: '#FBDB0F'
}, {
gt: 100,
lte: 150,
color: '#FC7D02'
}, {
gt: 150,
lte: 200,
color: '#FD0100'
}, {
gt: 200,
lte: 300,
color: '#AA069F'
}, {
gt: 300,
color: '#AC3B2A'
}],
outOfRange: {
color: '#999'
}
},
You can see the points in the different colors if you uncomment the visualMap in the codepen example and change "showSymbol" in the last item in the series to true.
This one was close, but I haven't been able to figure out how to get both the origin and end to create the line properly (x2 and y2 are both static); also, this seems to produce a bunch of separate lines, rather than a line series:
renderItem: function (params, api) {
var coord = api.coord([api.value(0), api.value(1)]);
return {
type: 'line',
shape: {
x1: coord[0],
y1: coord[1],
x2: 200,
y2: 100
},
style: { stroke: formatDirectionLabel(api.value(1)), lineWidth: 2 }
}
}
Example of the data (this is time, wind speed, wind gust, wind direction, and temp); I use map to transform that into simple arrays when it's pulled:
{"dt":"2021-02-18 06:33:10","w":"7.38","g":"9.84","dir":"343","f":"47.70"}
My goal is to display a line - time is the X axis, wind speed is the y axis, and color the line based on wind direction. Like I said, all of it would work if I just wanted to color the points, but that would make the graph really cluttered (not what I'm going for).
How do I color each line segment based on wind direction? Can someone provide a simple example of passing data in to render a custom line using renderItem?
With a whole bunch of trial and error, I got it working. The solution was using params.dataIndexInside+1 to produce the next item in the series. renderItem contents:
let coord1 = api.coord([api.value(0, params.dataIndexInside), api.value(1, params.dataIndexInside)]),
coord2 = api.coord([api.value(0, params.dataIndexInside+1), api.value(1, params.dataIndexInside+1)]);
return {
type: 'line',
shape: {
x1: coord1[0],
y1: coord1[1],
x2: coord2[0],
y2: coord2[1]
},
style: {
stroke: customFormattingFunction(api.value(3))
}
},
Hope that saves someone some time

Highchart area range on a plot column

I would like to set my area range (the blue horizontal bar) only on the red bar (fidding the width of the red bar) but I cannot find a solution to do this. Plot band don't work because it's full width on x axis. Could you help me please ?
On this try I managed to set the area range (blue horizontal bar) but it created another entry on X axis ("1"), I want to keep only the first entry "Omburu" with the same disposition of yellow, orange and red bar. With additionnal horizontal blue bar on the red bar who is set between to values following "Puissance kW" scale.
The JSFiddle is here : https://jsfiddle.net/poloh11/1qzfgopy/11/
Thanks a lot
{
name: 'Range',
data: [
[1000, 1500],[1000, 1500]
],
type: 'arearange',
lineWidth: 0,
color: Highcharts.getOptions().colors[0],
fillOpacity: 0.3,
marker: {
enabled: false
},
yAxis: 1
}
Use columnrage series instead. It has common properties with column series (pointRange, pointPadding etc.) that allow to adjust it similarly. The following configuration works for me:
{
name: 'Range',
data: [
[1000, 1500]
],
type: 'columnrange',
lineWidth: 0,
color: 'rgba(149,206,255,0.7)',
marker: {
enabled: false
},
yAxis: 1,
pointPlacement: 0.3,
pointRange: 0.33,
borderWidth: 0
}
Live demo: https://jsfiddle.net/BlackLabel/9czvmhsx/
API reference: https://jsfiddle.net/BlackLabel/9czvmhsx/

Highcharts Solid Gauge with min number NOT zero

I want to make a solid gauge using High Chart but I want my yAxis min value to be anything but zero. Whenever, I change the value, the label disappears. Is there a way to make the label appear again? Or maybe someone has an alternative way to make those labels.
In my project, I will have to change the min amount dynamically, depending on user's settings.
Here's a fiddle sample:
jsfiddle.net/TH2aB/1/
You can get the label back by specifying startOnTick:true,
yAxis: {
stops: [
[0.1, '#55BF3B'], // green
[0.5, '#DDDF0D'], // yellow
[0.9, '#DF5353'] // red
],
lineWidth: 0,
minorTickInterval: null,
tickPixelInterval: 400,
tickWidth: 0,
startOnTick:true,
title: {
y: -70
},
labels: {
y: 16
}
},
http://jsfiddle.net/yU7EM/
You can also explicitly set the tick positions using the tickPOsitions option:
tickPositions:[10,200],
http://jsfiddle.net/L6vVr/

How to customize the Gauge control?

Looking at the radial gauge control.was wondering if it would be possible to make it to look like the following picture, without the needle?
You can get pretty close doing:
$("#gauge").kendoRadialGauge({
pointer: {
// Current value
value: 0.72
},
scale: {
// Start and End angle of the Gauge
startAngle: 0,
endAngle: 180,
// Make range wider and with units inside
rangeSize: 40,
rangeDistance: -10,
// Configure major and minor unit
minorUnit: 0.05,
majorUnit: 0.25,
// Make major ticks same size than minor ticks
majorTicks: {
size: 10
},
// Define min and max (0% - 100%)
min: 0,
max: 1,
// Labels outside the range and number as percentage with no decimals
labels: {
position: "outside",
format: "p0"
},
// Color ranges
ranges: [
{
from: 0,
to: 0.45,
color: "red"
},
{
from: 0.45,
to: 0.80,
color: "yellow"
},
{
from: 0.80,
to: 1.00,
color: "green"
}
]
}
});
Some differences are:
The pointer is solid, you can configure the color but not the border:
There is no "Average" annotation.
You can see it here : http://jsfiddle.net/OnaBai/sThK3/1/
This is quite an old question, but there is a working answer here:
Give a Linear Gauge custom labels

Categories

Resources