Is there a way to prefix colours in raphael's pie chart? I need to be able to display for example gold in yellow and platinum in grey. The problem that I have at the moment is that if platinum has a higher value for e.g. 60% and gold 40% the platinum is displayed in yellow.
var r = Raphael("pieChartHolder");
var pie = r.piechart(155, 100, 50, [30, 60, 5, 5], {
colors: ['#FFDE7B', '#CFD0C6', '#E0DED9', '#93948C'],
legend: ['%%gold', '%%silver', '%%palladium', '%%platinum'],
legendpos: 'west'
});
pie.hover(function() {
this.sector.stop();
this.sector.scale(1.1, 1.1, this.cx, this.cy);
if (this.label) {
this.label[0].stop();
this.label[0].attr({
r: 7.5
});
this.label[1].attr({
"font-weight": 800
});
}
}, function() {
this.sector.animate({
transform: 's1 1 ' + this.cx + ' ' + this.cy
}, 500, "bounce");
if (this.label) {
this.label[0].animate({
r: 5
}, 500, "bounce");
this.label[1].attr({
"font-weight": 400
});
}
});
});
Just add matchColors : true
opts.matchColors forces it to match the order of the colors array with the order of the values array. I saw it here:
https://stackoverflow.com/a/14349559
Why do you want to prefix colors? If the library ignores order of items and sorts them itself then you should pass already sorted items.
I included the underscore.js library and sorted your items in descending order.
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="raphael-min.js"></script>
<script type="text/javascript" src="g.raphael-min.js"></script>
<script type="text/javascript" src="g.pie-min.js"></script>
<script type="text/javascript">
function drawChart() {
var r = Raphael("pieChartHolder");
var items = [
{ value: 30, color: '#FFDE7B', title: '%%gold' },
{ value: 60, color: '#CFD0C6', title: '%%silver' },
{ value: 5, color: '#E0DED9', title: '%%palladium' },
{ value: 5, color: '#93948C', title: '%%platinum' }
];
items = _.sortBy(items, function(item){ return -item.value; }); // sort by descending
var pie = r.piechart(155, 100, 50, _.pluck(items, "value"), {
colors: _.pluck(items, "color"),
legend: _.pluck(items, "title"),
legendpos: 'west'
});
pie.hover(function() {
this.sector.stop();
this.sector.scale(1.1, 1.1, this.cx, this.cy);
if (this.label) {
this.label[0].stop();
this.label[0].attr({
r: 7.5
});
this.label[1].attr({
"font-weight": 800
});
}
}, function() {
this.sector.animate({
transform: 's1 1 ' + this.cx + ' ' + this.cy
}, 500, "bounce");
if (this.label) {
this.label[0].animate({
r: 5
}, 500, "bounce");
this.label[1].attr({
"font-weight": 400
});
}
});
}
window.onload = drawChart;
</script>
<div id="pieChartHolder"></div>
Related
<div id="thelinechart" style="width: 1000px; height: 550px"></div>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script>google.charts.load('current', {'packages':['line']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();data.addColumn('string','Year');
data.addColumn('number','Current Trend');
data.addColumn('number','2015 Projection');
data.addColumn('number','2016 Projection');
data.addColumn('number','2017 Projection');
data.addColumn('number','2018 Projection');
data.addRows([
['2015',250,250,null,null,null],['2016',200,300,200,null,null],['2017',200,310,230,200,null],['2018',290,340,320,280,290],['2019',null,370,350,360,290],['2020',null,null,430,470,390],['2021',null,null,null,520,440],['2022',null,null,null,null,450]
]);
var options = {
chart: {
title: 'Capacity',
subtitle: 'in weight'
},
width: 850,
height: 450,
vAxis: {
viewWindowMode: 'explicit',
viewWindow: {
//max: 8000,
min: 0,
},
gridlines: {
count: 18, //set kind of step (max-min)/count
}
}
};
var chart = new google.charts.Line(document.getElementById('thelinechart'));
chart.draw(data, options);
}
</script>
I dont know how to fix this, and I have tried other maps from google as well but it doesnt seems to help me out in figuring out whats going wrong and why the y axis is not ordered from 0.
when using a material chart,
you need to use the following static method to convert the options to material options...
google.charts.Line.convertOptions(options)
see following working snippet...
google.charts.load('current', {
packages: ['line']
}).then(function () {
var data = new google.visualization.DataTable();data.addColumn('string','Year');
data.addColumn('number','Current Trend');
data.addColumn('number','2015 Projection');
data.addColumn('number','2016 Projection');
data.addColumn('number','2017 Projection');
data.addColumn('number','2018 Projection');
data.addRows([
['2015',250,250,null,null,null],['2016',200,300,200,null,null],['2017',200,310,230,200,null],['2018',290,340,320,280,290],['2019',null,370,350,360,290],['2020',null,null,430,470,390],['2021',null,null,null,520,440],['2022',null,null,null,null,450]
]);
var options = {
chart: {
title: 'Capacity',
subtitle: 'in weight'
},
width: 850,
height: 450,
vAxis: {
viewWindowMode: 'explicit',
viewWindow: {
//max: 8000,
min: 0,
},
gridlines: {
count: 18, //set kind of step (max-min)/count
}
}
};
var chart = new google.charts.Line(document.getElementById('thelinechart'));
chart.draw(data, google.charts.Line.convertOptions(options));
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="thelinechart"></div>
NOTE: there are also several options that are not supported by material charts,
see --> Tracking Issue for Material Chart Feature Parity
My questions (short style)
Can you customize a y-axis labeling interval ?
Can you display the extreme values of a series as an horizontal line ?
The detailed explanations
I have a combo chart made with Google Charts : the first set of data uses an area style, and the second a line style. The second one is the one that matters here :
it represents a percentage
i don't want it from 0 to 1 (or 0 to 100 in percentage), but from its min to its max (or something near)
and i want to display those min and max values
If i modify the scale so :
PHP
$min_reject_percentage = 5 * floor($min_reject_percentage / 5);
$max_reject_percentage = 5 * ceil($max_reject_percentage / 5);
JS
var options = {
...
vAxes: {
...
1: {
format:"##%",
viewWindow: {
min: <?php echo ($min_taux_rejet / 100); ?>,
max: <?php echo ($max_taux_rejet / 100); ?>,
},
},
},
series: {
0: {
targetAxisIndex: 0,
type: 'area',
},
1: {
targetAxisIndex: 1,
type: 'line',
},
}
}
The vertical axis is limited to the nearest multiple of 5 for min and max values, but :
the interval shown on the axis is from 10 to 10, which is too big. Since i have a real max of 31.5 and a real min of 17.1, axis min is 15 is 15 and axis max is 35, but the only graduation labeled are 20 and 30.
i can't see the real min and max on the graph
you can use config option ticks, which is an array of values to be used for the labels...
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['x', 'y0', 'y1'],
[0, 18, 0.171],
[1, 28, 0.315],
]);
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
var axisMin = 0.15;
var axisMax = 0.35;
var ticks = [];
for (var i = axisMin; i <= axisMax; i = i + 0.05) {
ticks.push(i);
}
var options = {
vAxes: {
1: {
format: '##%',
ticks: ticks,
viewWindow: {
min: axisMin,
max: axisMax,
},
},
},
series: {
0: {
targetAxisIndex: 0,
type: 'area',
},
1: {
targetAxisIndex: 1,
type: 'line',
},
}
};
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
Let's say I have a datatable like this:
drivingData.addColumn('string', 'VehicleGroup');
drivingData.addColumn('number', 'TimeType');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
then I add 4 rows like this:
drivingData.addRow(['Trucks-S',0, 1000, 1200])
drivingData.addRow(['Trucks-F',1, 300, 500])
drivingData.addRow(['Trailer-S',0, 1200, 1500])
drivingData.addRow(['Trailer-F',1, 100, 500])
I would like to have a 'stacked' column chart. First one shows Trucks-S with TimeType 0 with yellow and orange colors.
Second would show Trucks-F with TimeType 1 with grey and light-grey colors.
Third would then again be yellow and orange and fourth grey and light-grey and so on...
Is this possible?
Something like this:
https://imgur.com/a/oNOiP
the requested chart is only available as a Material bar chart
Material --> google.charts.Bar -- packages: ['bar']
Classic --> google.visualization.ColumnChart -- packages: ['corechart']
you can break Material bar charts into multiple stacks,
by assigning a group of series to a different y-axis
this is accomplished by using the series option
series: {
2: {
targetAxisIndex: 1
},
3: {
targetAxisIndex: 1
}
},
this will create a second axis on the right side of the chart,
which will have a different scale by default
to keep both y-axis in sync, assign a specific view window
vAxis: {
viewWindow: {
min: 0,
max: 3000
}
}
see following working snippet...
google.charts.load('current', {
packages: ['bar']
}).then(function () {
var drivingData = new google.visualization.DataTable();
drivingData.addColumn('string', 'VehicleGroup');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
drivingData.addRow(['Trucks-S', 1000, 1200, 600, 800])
drivingData.addRow(['Trucks-F', 300, 500, 700, 900])
drivingData.addRow(['Trailer-S', 1200, 1500, 800, 1000])
drivingData.addRow(['Trailer-F', 100, 500, 600, 1000])
var container = document.getElementById('chart_div');
var chart = new google.charts.Bar(container);
var options = google.charts.Bar.convertOptions({
colors: ['#fbc02d', '#616161'],
height: 400,
isStacked: true,
series: {
2: {
targetAxisIndex: 1
},
3: {
targetAxisIndex: 1
}
},
vAxis: {
viewWindow: {
min: 0,
max: 3000
}
}
});
chart.draw(drivingData, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
note: just keep in mind,
there are several configuration options that are not supported by Material charts
see --> Tracking Issue for Material Chart Feature Parity
EDIT
isStacked: 'percent' is currently not support by Material charts
to work around this issue, convert the data manually, before drawing the chart
see following working snippet,
y-axis columns will be converted in groups of two...
google.charts.load('current', {
packages: ['bar']
}).then(function () {
var drivingData = new google.visualization.DataTable();
drivingData.addColumn('string', 'VehicleGroup');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
drivingData.addRow(['Trucks-S', 1000, 1200, 600, 800])
drivingData.addRow(['Trucks-F', 300, 500, 700, 900])
drivingData.addRow(['Trailer-S', 1200, 1500, 800, 1000])
drivingData.addRow(['Trailer-F', 100, 500, 600, 1000])
// convert data to percent
var percentData = new google.visualization.DataTable();
for (var col = 0; col < drivingData.getNumberOfColumns(); col++) {
percentData.addColumn(drivingData.getColumnType(col), drivingData.getColumnLabel(col));
}
for (var row = 0; row < drivingData.getNumberOfRows(); row++) {
var newRow = percentData.addRow();
percentData.setValue(newRow, 0, drivingData.getValue(row, 0));
for (var col = 1; col < drivingData.getNumberOfColumns(); col++) {
if ((col % 2) !== 0) {
var rowTotal = drivingData.getValue(row, col) + drivingData.getValue(row, (col + 1));
percentData.setValue(newRow, col, (drivingData.getValue(row, col) / rowTotal));
percentData.setValue(newRow, (col + 1), (drivingData.getValue(row, (col + 1)) / rowTotal));
}
}
}
var container = document.getElementById('chart_div');
var chart = new google.charts.Bar(container);
var options = google.charts.Bar.convertOptions({
colors: ['#fbc02d', '#616161'],
height: 400,
isStacked: true,
series: {
2: {
targetAxisIndex: 1
},
3: {
targetAxisIndex: 1
}
},
vAxis: {
format: '0%',
viewWindow: {
min: 0,
max: 1
}
}
});
chart.draw(percentData, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
I need your help, i try use "pattern" in Highcharts to use background in bars, but the images don't fill the space that i wanna.
Bar Chart Example
I wanna know, how i do to leave the image with -90° than the way that is? And how i do to leave the image with height 100% and width 25%?
And beyond that i wanna of know, how i print the screen without lose the quality in image, because when i press "ctrl+p" i see all all blurred.
Print blurred
Follow below the current code:
<!DOCTYPE html>
<html>
<head>
<title>HighCharts - Pattern Color</title>
<meta http-equiv="Content-Type" contetn="text/html;" charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css" />
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.9.1/jquery-ui.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://highcharts.github.io/pattern-fill/pattern-fill.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
Highcharts.chart('container', {
chart: {
type: 'bar',
backgroundColor: null
},
title: {
text: 'Como você está?'
},
xAxis: {
categories: ['']
},
yAxis: {
min: 0,
title: {
text: ''
}
},
legend: {
reversed: true
},
plotOptions: {
series: {
stacking: 'percent',
dataLabels: {
enabled: true,
format: '<b>{point.percentage:.2f}%</b>',
//point.percentage:.1f
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: [{
name: 'Alegre',
data: [30],
color: {
pattern: 'http://emoticons.topfriends.biz/favicon.png',
width: '30',
height: '30'
}
// color: '#B22222'
}, {
name: 'Feliz',
data: [30],
color: {
pattern: 'https://t4.ftcdn.net/jpg/01/58/30/09/240_F_158300957_MhRWEx1vDO6SPVHdGS4dqNG7nLP8rdZ4.jpg',
width: '30',
height: '30'
}
// color: '#2E8B57'
}]
});
});
</script>
<div id="container" style="min-width: 80%; height: 200px; max-width: 80%; margin: 0 auto"></div>
</body>
</html>
Since now i thanks!
1. PATTERN FILL ADJUSTMENT
Refer to this live working example: http://jsfiddle.net/kkulig/opa73k8L/
Full code:
var redrawEnabled = true,
ctr = 0;
$('#container').highcharts({
chart: {
events: {
render: function() {
if (redrawEnabled) {
redrawEnabled = false;
var chart = this,
renderer = chart.renderer;
chart.series[0].points.forEach(function(p) {
var widthRatio = p.shapeArgs.width / p.shapeArgs.height,
id = 'pattern-' + p.index + '-' + ctr;
var pattern = renderer.createElement('pattern').add(renderer.defs).attr({
width: 1,
height: widthRatio,
id: id,
patternContentUnits: 'objectBoundingBox'
});
renderer.image('http://emoticons.topfriends.biz/favicon.png', 0, 0, 1, widthRatio).attr({
}).add(pattern);
p.update({
color: 'url(#' + id + ')'
}, false);
});
ctr++;
chart.redraw();
redrawEnabled = true;
}
}
}
},
series: [{
type: 'bar',
borderWidth: 1,
borderColor: '#000000',
data: [10, 29.9, 71.5]
}]
});
In the redraw event I iterate all the points, create a separate pattern for every point based on its width/height ratio, apply pattern and redraw the chart.
On every redraw new set of patters are created which is not an elegant solution (old ones should be replaced instead). ctr variable is used to create unique name for each pattern.
redrawEnabled serves to prevent infinite recursive loop because chart.redraw() also calls the render event.
In my opinion the easiest way to have the rotated image is to simply provide the already rotated one.
API references:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#createElement
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#image
2. PRINTING ISSUE
It seems to be a bug reported here: https://github.com/highcharts/pattern-fill/issues/20
I need a one column column-chart that has a vertical axis from 0 to 150000 and a bar that fills it (they have met their deductible completely). I thought I had what I read to do this as below, but that gives me a vertical axis of 0 to 400,000 and a bar up to 150,000.
Alternatively, I could use suggestions on how to display a single field whereas one can pay in full or in 4 payments to meet that deductible.
PLEASE help!
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(barDisassembly);
function barDisassembly() {
var data = google.visualization.arrayToDataTable([
['Categories', 'Disassembly Fee'],
['N-1701', 150000]
]);
var options = {
chart: {
width: 200,
height: 400,
legend: { position: 'top', maxLines: 3 },
vAxis: {
viewWindowMode:'explicit',
viewWindow:{
max:150000,
min:0
}
}
}
};
var bar = new google.visualization.ColumnChart(document.getElementById('bar_disassembly'));
bar.draw(data, options);
}
</script>
Remove chart from the options.
The only configuration options associated with chart are subtitle and title...
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(barDisassembly);
function barDisassembly() {
var data = google.visualization.arrayToDataTable([
['Categories', 'Disassembly Fee'],
['N-1701', 150000]
]);
var options = {
width: 400,
height: 400,
legend: {
position: 'top',
maxLines: 3
},
vAxis: {
viewWindow: {
max: 150000,
min: 0
}
}
};
var bar = new google.visualization.ColumnChart(document.getElementById('bar_disassembly'));
bar.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="bar_disassembly"></div>