Recharts: Change background fill color of RadialBar chart based on fill color in data - recharts

I want to use the low-opacity version of the fill color defined in the data object as the background fill color of the RadialBar chart.
I tried using a function as the background property of <RadialBar />, but it doesn't seem to get any arguments.
const data = [
{ name: 'foo', value: 1, fill: 'red' },
{ name: 'bar', value: 2, fill: 'blue' },
];
<RadialBarChart
width={260}
height={260}
innerRadius={80}
outerRadius={130}
startAngle={90}
endAngle={-270}
margin={{ top: 0, right: 0, bottom: 0, left: 0 }}
barSize={12}
data={data}
>
<RadialBar
minAngle={15}
clockWise
dataKey="value"
cornerRadius="5"
background={(foo) => { console.log(foo); }}
/>
</RadialBarChart>
Any idea how I can access the color of the corresponding sector?

Not sure if I understand you correctly, but if you need to change the background colour of the RadialBar, you can assign an object to the "background" property, and if you need to change the fill colour you can change the "fill" property such as here:
<RadialBar
background={{ fill: data[0].fill }}
fill={data[0].fill}
/>

Expanding on Dmitry's answer, you can set opacity as well.
The issue I had was the chart doesn't work with different colour themes, specifically light and dark mode.
To fix this, set background fill to "rgba(0, 0, 0, opacity)" where the 4th value ranges from 0 to 1
e.g. for 5% opacity (mostly transparent)
<RadialBar
background={{ fill: rgba(0, 0, 0, 0.05) }}
dataKey="<yourdatakey>"
/>

Try this out, using react memo to change the fill property in radialBarChart.
data={React.useMemo(
() => [
{
percentage,
fill: 'currentColor',
},
],
[percentage],
)}
and set a div for this.
<div className={{
color: 'green',
}} >
<RadialBarChart data={React.UseMemo(..etc)}>
<RadiaBar (radial props) />
</RadialBarChart>
</div>

Related

How to change text in multiple lines / places of a Textbox in FabricJS?

I need to replace text of particular selection when the input value has been changed.
On the initial rendering, I get an object of selections and fields.
Secondly, inputs get values of fields.
Assume I'm changing a value of the Line input, since this field controls two lines, both of those green texts should be replaced with the new one.
http://jsfiddle.net/hkvmLwfu/
Tnx
////////////////////////////////////////////////////////////////////////
/////////////// THIS FUNCTION NEEDS TO BE DEVELOPED ////////////////////
////////////////////////////////////////////////////////////////////////
function replaceTextBySelection(fieldId, fieldValue, canvas, text){
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
var canvas = new fabric.Canvas('paper');
canvas.setHeight(300);
canvas.setWidth(500);
var text = new fabric.Textbox('Sample Line 1 Line 2 Line 3', {
left: 50,
top: 10,
fontFamily: 'arial',
fill: '#333',
fontSize: 50
});
canvas.add(text);
canvas.renderAll();
const fields = {
FIELD_1: {
value: "Sample",
color: '#F00'
},
FIELD_2: {
value: "Line",
color: '#0F0'
}
}
selections = [
{
rowId: 0,
offset: 0,
length: 6,
field: "FIELD_1"
},
{
rowId: 1,
offset: 0,
length: 4,
field: "FIELD_2"
},
{
rowId: 2,
offset: 0,
length: 4,
field: "FIELD_2"
}
]
selections.map((obj)=>{
text.setSelectionStart(obj.offset);
text.setSelectionEnd(obj.offset + obj.length);
text.setSelectionStyles();
for (let i = text.selectionStart; i < text.selectionEnd; i++) {
text.insertCharStyleObject(obj.rowId, i, {
textBackgroundColor: fields[obj.field].color
})
}
canvas.renderAll();
return obj;
});
$('#FIELD_1').val( fields['FIELD_1'].value );
$('#FIELD_2').val( fields['FIELD_2'].value );
$("input").keyup(function(t){
replaceTextBySelection(this.id, this.value, canvas, text);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.min.js"></script>
<canvas id="paper" width="400" height="400" style="border:1px solid #ccc"></canvas>
<input type="text" id="FIELD_1" />
<br/>
<input type="text" id="FIELD_2" />
Your example complicates things because the selections object reasons about rows, but the text doesn't actually contain rows, only spaces that get wrapped to a new line.
It gets easier if you define your text instead as
var text = new fabric.Textbox('Sample\nLine 1\nLine 2\nLine 3', {
left: 50,
top: 10,
fontFamily: 'arial',
fill: '#333',
fontSize: 50
});
Using this text I have created a functional example: http://jsfiddle.net/hkvmLwfu/12/. I'm not sure this is entirely how you want it, but you should be able to pick it up from here.
Just use \n where you want to break the line. It will work like <br/>.

AppBar iconElementRight admin-on-rest

I'm using example from https://marmelab.com/admin-on-rest/Theming.html#using-a-custom-layout.
Added a new IconMenu as in the snippet below. The right menu icon does not get displayed. Tested component by invoking it from a different form, and it works. However, integrating it into AppBar does not work.
Looks like either the styles or something else is interfering with it.
Has anyone got such a menu working well with AppLayout customizations?
const styles = {
// Snipped rest of the styles from example
loader: {
position: 'absolute',
top: 0,
right: 50,
margin: 16,
zIndex: 1200,
},
iconMenu: {
position: 'absolute',
top: 0,
right: 0,
margin: 16,
zIndex: 1200,
},
};
const AppBarMenu = (props) => (
<IconMenu {...props}
iconButtonElement={
<IconButton><MoreVertIcon /></IconButton>
}
targetOrigin={{horizontal: 'right', vertical: 'top'}}
anchorOrigin={{horizontal: 'right', vertical: 'top'}}
>
<MenuItem primaryText="Settings" />
<MenuItem primaryText="About" />
<MenuItem primaryText="Sign out" />
</IconMenu>
);
AppBarMenu.muiName = 'IconMenu';
<AppBar title={title} iconElementRight={<AppBarMenu style={styles.iconMenu} />} />
Used proposal in https://github.com/marmelab/admin-on-rest/issues/525
Quote from above URL:
If anyone wants buttons in the title bar, they will have to have not only a custom layout, but copy AppBar.js from admin-on-rest into their project and import that. Inside AppBar.js, iconElementRight works inside the MuiAppBar tags, but not inside Layout.js.

Remove borders around swatches on legend for Pie graph (jqplot)

How do I remove the border around the swatches in the legend of a JQPlot graph? Below is my code. There is a border around the swatches, but the border is bigger than the square and I would prefer to remove it. Then this might be a second question (and I will remove if someone just answers one or asks me to): I have 4 sets of the raw data for every slice. How to I show more of this data in the legend (eg: the name and the amount and percentage)
Below is the code I have:
var budgetGraph = [["GROCERIES",4194.02,57.95302704323518,10],["BUSINESS MISCELLANEOUS",918.19,12.68756226742555,102],["HEALTHCARE/MEDICAL",729.65,10.082313909351063,11],["HOBBIES/SPORT",502.56,6.944381111880313,34],["OTHER EXPENSES",492.7,6.808135493918,19],["Other",399.81,5.524580174189884,0]];
var plot1 = jQuery.jqplot ('budgetGraph', [budgetGraph],
{
seriesDefaults: {
// Make this a pie chart.
renderer: jQuery.jqplot.PieRenderer,
rendererOptions: {
},
seriesColors: graphColours.pie
},
legend: {
renderer: jQuery.jqplot.PieLegendRenderer,
show: true,
renderOptions: {
numberColumns: 3
},
location: 'e',
placement: 'outside',
border: 'none'
},
grid: {
drawGridLines: false, // wether to draw lines across the grid or not.
gridLineColor: 'transparent', // CSS color spec of the grid lines.
background: 'transparent', // CSS color spec for background color of grid.
borderColor: 'transparent', // CSS color spec for border around grid.
borderWidth: 0.0, // pixel width of border around grid.
shadow: false // draw a shadow for grid.
}
}
);
You can remove the outline by overriding the css class:
.jqplot-table-legend-swatch-outline { border: 0 solid #CCCCCC;}
For your second question you can use the "labels" option of the legend:
legend: {
show: true,
location: 'ne',
placement: "outside",
labels: legendLabels
}
and before calling the jqplot function populate the legendLabels array like this:
var legendLabels= ['label1 with data or %', 'label2 with data or %', 'label3 with data or %'];

How to use Jqplot to show two groups of differently colored bars in the same stacked bar chart

I want to make a bar chart with two sets of stacked bars which are grouped together to compare the two groups of stacked bars. This should be displayed in the following manner:
I have gone through this link
But it didn't help me plot something like you see in the above image. I even tried sending two data sets like [[s1, s2, s3], [s4, s5, s6]] But it didn't help me plot the chart.
Does anyone know how to do it?
Any help will be greatly appreciated.
Thanks in advance.
Setting the option stackSeries: true will create the desired display for bar charts.
Official sources:
jqPlot Source code: source code, version 1.0.8r1250 of
2013-03-27. For this issue, src/jqplot.core.js lines 2499, 2563, and 2649.
jqPlot Documentation: It says that the API Documentation is most accurate. you can also see the webpage, README.txt,
optionsTutorial.txt, jqPlotOptions.txt, jqPlotOptions.txt,
jqPlotCssStyling.txt, usage.txt, changes.txt in the 1.0.8r1250
general release
The jqPlot documentation is not up to date so I took a look at the source code. Unfortunately, there is no way to directly have two sets of bars with a stacked-bar chart. The jqPlot.stackSeries property is only a boolean value. It's only function is to tell jqPlot to stack each series on top of each other for as many bars as there are values in the different series. Each series is plotted one value per bar with the first series being on the bottom. In other words, all [0] values are plotted in the first bar, [1] values in the second, etc. The amount shown within the bar is the sum of the [n] value for the current series and all prior series. There is no way to specify that there are two, or more, groupings of series. The capability to do what is desired just does not exist in jqPlot.
But you can accomplish what you desire:
The fact that jqPlot does not natively support what you want does not mean that you can not do it, merely that you need to get creative.
The graph you desire can be looked at as being two separate graphs that have been overlaid upon each other with spacing between the bars on the individual graphs permitting enough space (seriesDefaults.rendererOptions.barMargin) for the bars from the other graph to be overlaid next to them.
You can use jqPlot to create:
That graph has the scale, background and grid-lines you desire set to be visible. Note that the graph has an extra bar in it. This is needed to provide enough background and grid-lines for the last bar provided by the other graph.
You can also use jqPlot to create the second graph:
This graph has the scale and grid-lines set in jqPlot to not be visible.
seriesDefaults.axes.xaxis.tickOptions.show = false;
seriesDefaults.axes.yaxis.tickOptions.show = false;
etc.
The background is set to be transparent. Note that you are going to need to offset the position of this graph somewhat to the right when positioning the <div> relative to the first graph.
Overlaid, you end up with:
You then use a blank <div> with the same background color as the background color of your webpage and overlay that to cover the extra bar on the first graph, but leaving enough of the first graph's background and grid-lines to extend a bit past the last bar of the second graph.
You will end up with:
You can see a working solution at at JSFiddle using jqPlot 1.0.8r1250.
Comparing the original request vs. the final version of the graph produced using this method you can see that they are very close:
Between the two the most noticeable difference is the larger space between the Y-axis in the jqPlot version. Unfortunately, there does not appear to be an option to reduce that amount for stacked bar charts.
Note that the lack of a border on the right of the graph this code produces is intentional because it did not exist in the original request. Personally, I prefer having a border on the right side of the graph. If you change the CSS a bit, that is easy to obtain:
My preferred version of the graph includes a border on the left and balances the whitespace:
You can see a working JSFiddle of this version.
All-in-all it is not that difficult. It would, of course, be easier if jqPlot supported multiple sets of bars. Hopefully it will at some point. However, the last release was 2013-03-27 and there does not appear to have been any development work after that time. Prior to that there were releases every few months. But, jqPlot is released under the GPL and MIT licenses so anyone could continue the work.
$(document).ready(function () {
//Numbers derived from desired image
//var s1 = [10, 29, 35, 48, 0];
//var s2 = [34, 24, 15, 20, 0];
//var s3 = [18, 19, 26, 52, 0];
//Scale to get 30 max on plot
var s1 = [2, 5.8, 7, 9.6, 0];
var s2 = [6.8, 4.8, 3, 4, 0];
var s3 = [13.6, 8.8, 3, 7.8, 0];
plot4 = $.jqplot('chart4', [s1, s2, s3], {
// Tell the plot to stack the bars.
stackSeries: true,
captureRightClick: true,
seriesColors: ["#1B95D9", "#A5BC4E", "#E48701"],
seriesDefaults: {
shadow: false,
renderer: $.jqplot.BarRenderer,
rendererOptions: {
// jqPlot does not actually obey these except barWidth.
barPadding: 0,
barMargin: 66,
barWidth: 38,
// Highlight bars when mouse button pressed.
// Disables default highlighting on mouse over.
highlightMouseDown: false
},
title: {
text: '', // title for the plot,
show: false,
},
markerOptions: {
show: false, // wether to show data point markers.
},
pointLabels: {
show: false
}
},
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
tickOptions: {
show: false
},
lastPropertyConvenience: 0
},
yaxis: {
// Don't pad out the bottom of the data range. By default,
// axes scaled as if data extended 10% above and below the
// actual range to prevent data points right on grid boundaries.
// Don't want to do that here.
padMin: 0
}
},
legend: {
show: false,
location: 'e',
placement: 'outside'
},
grid: {
drawGridLines: true, // wether to draw lines across the grid or not.
shadow: false, // no shadow
borderWidth: 1,
background: 'white', // CSS color spec for background color of grid.
lastPropertyConvenience: 0
},
lastPropertyConvenience: 0
});
});
$(document).ready(function () {
//Numbers derived from desired image
//var s1 = [10, 29, 35, 48, 0];
//var s2 = [34, 24, 15, 20, 0];
//var s3 = [18, 19, 26, 52, 0];
//Scale to get 30 max on plot
var s1 = [2, 5.8, 7, 9.6, 0];
var s2 = [6.8, 4.8, 3, 4, 0];
var s3 = [3.6, 3.8, 5.2, 10.4, 0];
plot4 = $.jqplot('chart5', [s1, s2, s3], {
// Tell the plot to stack the bars.
stackSeries: true,
captureRightClick: true,
seriesColors: ["#754DE9", "#666666", "#000000"],
seriesDefaults: {
shadow: false,
renderer: $.jqplot.BarRenderer,
rendererOptions: {
// jqPlot does not obey these options except barWidth.
show: true,
barPadding: 0,
barMargin: 66,
barWidth: 38,
// Highlight bars when mouse button pressed.
// Disables default highlighting on mouse over.
highlightMouseDown: false
},
title: {
text: '', // title for the plot,
show: false,
},
markerOptions: {
show: false, // wether to show data point markers.
},
pointLabels: {
show: false
}
},
axesDefaults: {
//show: false
},
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
tickOptions: {
show: false
},
lastPropertyConvenience: 0
},
yaxis: {
show: false,
// Don't pad out the bottom of the data range. By default,
// axes scaled as if data extended 10% above and below the
// actual range to prevent data points right on grid boundaries.
// Don't want to do that here.
padMin: 0,
tickOptions: {
show: false
},
}
},
legend: {
show: false,
location: 'e',
placement: 'outside'
},
grid: {
drawGridLines: false, // wether to draw lines across the grid or not.
shadow: false, // no shadow
borderWidth: 10,
background: 'transparent', // CSS color for background color of grid.
gridLineColor: 'transparent', // *Color of the grid lines.
borderColor: 'transparent', // CSS color for border around grid.
lastPropertyConvenience: 0
},
lastPropertyConvenience: 0
});
});
#cover1 {
padding:0;
margin: 0;
background-color: white;
left: 451px;
width: 88px;
/* Uncomment the next three lines to have a border on the right of the graph and
balanced whitespace:*/
/*
border-left: 2px solid #CCCCCC;
left:476px;
width: 62px;
*/
}
#chart4 .jqplot-xaxis-tick {
visibility: hidden;
}
#chart5 .jqplot-xaxis-tick {
visibility: hidden;
}
#chart4 .jqplot-yaxis-tick {
font: 9px arial
}
<link class="include" rel="stylesheet" type="text/css" href="http://cdn.jsdelivr.net/jqplot/1.0.8/jquery.jqplot.css" />
<!--[if lt IE 9]><script language="javascript" type="text/javascript" src="http://cdn.jsdelivr.net/excanvas/r3/excanvas.js"></script><![endif]-->
<script class="include" type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- Main jqPlot -->
<script class="include" type="text/javascript" src="http://cdn.jsdelivr.net/jqplot/1.0.8/jquery.jqplot.js"></script>
<!-- Additional jqPlot plugins -->
<script class="include" type="text/javascript" src="http://cdn.jsdelivr.net/jqplot/1.0.8/plugins/jqplot.barRenderer.min.js"></script>
<script class="include" type="text/javascript" src="http://cdn.jsdelivr.net/jqplot/1.0.8/plugins/jqplot.categoryAxisRenderer.min.js"></script>
<div style="position:absolute; left:10px; top:10px;">
<div id="chart4" style="width:548px; height:185px;"></div>
<div id="chart5" style="width:536px; height:185px; top:-185px; left:53px;"></div>
<div id="cover1" style="position: relative; height: 152px; top:-361px;"></div>
</div>
The above code is based on that at the example page listed in the question.
Practical solution...
$(document).ready(function(){
var s1 = [2, 0, 0, 10,11,0, 6, 2, 0,10,11];
var s2 = [7, 0, 0, 4,11,0, 6, 2, 0,10,11];
var s3 = [4, 0, 0, 7,11,0, 6, 2, 0,10,11];
var s4 = [0, 20, 0, 0,0,0, 0, 0, 0,0,0];
plot3 = $.jqplot('chart3', [s1, s2, s3,s4], {
stackSeries: true,
captureRightClick: true,
seriesDefaults:{
renderer:$.jqplot.BarRenderer,
rendererOptions: {
barMargin: 30,
highlightMouseDown: true
},
pointLabels: {show: true}
},
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer
},
yaxis: {
padMin: 0
}
},
legend: {
show: true,
location: 'e',
placement: 'outside'
}
});
$('#chart3').bind('jqplotDataClick',
function (ev, seriesIndex, pointIndex, data) {
$('#info3').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data);
}
);
});
Image:

Add Legend to jVectorMap

I am updating our application to use jVectorMap instead of a Flash. Some of the maps need the countries to be colored differently. This is pretty simple to create.
<div id="world-map-color" style="width: 900px; height: 600px;"></div>
<script>
var myData = {
"AF": 36.63,
"RU": 11.58,
"US": 158.97
};
$('#world-map-color').vectorMap({
backgroundColor: "#FFFFFF",
regionStyle: {
initial: { fill: "#7C96A1" },
hover: { fill: "#A0D1DC" }
},
series: {
regions: [{
values: myData,
scale: ['#B0ADF7', '#0D0885'],
normalizeFunction: 'polynomial'
}]
}
});
</script>
The resulting map:
However, I'd like to add some kind of legend/key to say what the scale of the colors are. Something like the following:
Additionally, that example legend (from Flash) allowed the user to change the scaling for the colors using those arrows on the top. So it'd be nice if that was possible as well.
Does anyone know if any parts of these are possible?
The most basic thing is necessary to achieve is the generation of the colorful scale. For that see the similar question I have answered recently.

Resources