<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.min.js"></script>
<div style="width:50%">
<canvas id="chart2" style="width:100%"></canvas>
</div>
<script>
var yLabels = {
1 : 'New',
2 : 'Learning Phase',
3 : 'Good',
4 : 'Strong',
5 : 'Master'
}
Chart.register(ChartDataLabels);
new Chart('chart2', {
type: 'bar',
data: {
labels: ['Tommy','Fred'],
datasets: [{
data: [3,1],
}]
},
options: {
indexAxis: 'y',
layout: {
padding: {
right: 60
}
},
plugins: {
title: {
display: true,
text: "Skill Chart"
},
legend: {
display: false,
},
datalabels: {
color: 'blue',
formatter: (value) => {
if (value == 1) {
value = 'New';
return value;
}
if (value == 2) {
value = 'Learning Phase';
return value;
}
if (value == 3) {
value = 'Good';
return value;
}
if (value == 4) {
value = 'Strong';
return value;
}
if (value == 5) {
value = 'Master';
return value;
}
},
anchor: 'end',
align: 'right',
labels: {
title: {
font: {
weight: 'bold'
}
}
}
}
},
scales: {
y: {
grid: {
display: false
},
ticks: {
},
},
x: {
ticks:{
callback: function(value, index, values) {
return yLabels[value];
},
precision: 1,
},
grid: {
display: false,
}
}
}
}
});
</script>
Above is a working code, but what I am facing right now is that how do I show 'all label that in the variable ylabels' in x-axis? I tried autoSkip:false. It does not work.
What I wanted is that it shows all the label from (new to master), despite that the data is only 3 and 1. If I changed the label to '5' everything work perfectly.
https://codepen.io/kennyl80841728/pen/jOxzLjy
You need to define options.scales.x.max as follows:
options: {
scales: {
x: {
max: 5,
...
For further information, please consult Min Max Configuration from the Chart.js documentation
Related
this is my donut chart (ApexCharts):
var options = {
series: [umsatzSum, ausgabenSum, auslagenSum],
chart: {
type: 'donut',
height: 320,
fontFamily: chartFontStyle
},
labels: ["Umsatz", "Ausgaben", "Auslagen"],
colors:['#7ebd0b', '#661818', "#333"],
track: {
background: "#cccccc"
},
dataLabels: {
enabled: false
},
stroke: {
colors:['#7ebd0b', '#661818', "#333"],
},
plotOptions: {
pie: {
donut: {
labels: {
show: true,
value: {
formatter: function (val,chart) {
let valPercent = val/chart.config.series.reduce((a, b) => a + b, 0)*100;
return Math.round(valPercent) + "%"
}
}
}
}
}
}
var chart = new ApexCharts(document.querySelector("#myChart"), options);
chart.render();
Result:
And If I mouse over a series element, it will show this:
And If I click on the series element, the percent value in the middle stays
How can I realize, that the percent value will be show at the beginning (after the chart was created), without hover or click an element first?
https://apexcharts.com/docs/options/plotoptions/pie/#total total will be shown when no series is selected or hovered over.
labels: {
show: true,
value: {
formatter: function (val,chart) {...}
},
total: {
show: true,
label: 'Umsatz',
color: '#7ebd0b',
formatter: function (chart) {
let seriesToShowId = 0
let val = chart.config.series[seriesToShowId]
let valPercent = val/chart.config.series.reduce((a, b) => a + b, 0)*100;
return Math.round(valPercent) + "%"
}
}
}
I am creating a high charts graph that I would like to dynamically give the graph color to depending on the title of an object. I currently have an array graphData that has an object title.
I have 5 possible results of titles:
"LOW", "MEDIUM-LOW", "MEDIUM", "MEDIUM-HIGH", AND "HIGH"
I am now attempting to iterate through my array and assign a color depending on what title the index has.
My entire graph receives one color based off the last title of the array. I would like the color to effect each index of the array seperartely.
For example: if "MEDIUM-HIGH" is the last title in the array, my entire graph gets #DD5F0C
Here is my code:
Array:
graphData: [ […]
0: Object { title: "LOW", result: 62582 }
1: Object { title: "MEDIUM-LOW", result: 57758 }
2: Object { title: "LOW", result: 8795 }
3: Object { title: "HIGH", result: 262525 }
4: Object { title: "MEDIUM-HIGH", result: 167168 } ]
let graphColor = ""
for (i = 0; i < graphData.length; i++) {
if (graphData[i].title === "LOW") {
graphColor = "#0D6302"
} else if (graphData[i].title === "MEDIUM-LOW") {
graphColor = "#0B7070"
} else if (graphData[i].title === "MEDIUM") {
graphColor = "#DC9603"
} else if (graphData[i].title === "MEDIUM-HIGH") {
graphColor = "#DD5F0C"
} else if (graphData[i].title === "HIGH") {
graphColor = "#C50710"
}
}
HighCharts code :
Highcharts.chart('container', {
chart: {
type: 'bar'
},
title: {
text: "Bar Graph"
},
xAxis: {
},
yAxis: {
min: 0,
formatter: function() {
return this.value + "%";
},
title: {
text: '% of Total'
}
},
legend: {
reversed: false
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [{
name: `graphData[0].title`,
color: graphColor,
data: [graphData[0]],
}, {
name: 'graphData[1].title',
color: graphColor,
data: [graphData[1]],
showInLegend: false,
linkedTo: ":previous"
}, {
name: 'graphData[2].title,
color: graphData[0].title,
data: [graphData[2]]
}, {
name: graphData[3].title,
color: '#DC9603',
data: [graphData[3]]
}, {
name: graphData[4].title,
color: graphColor,
data: [graphData[4]]
}, {
name: graphData[5].title,
color: graphColor,
data: [graphData[5]]
}]
});
I am expecting my "color" to be dynamically generated based off of what graphData.title equals for that specific index.
You are having trouble because you have graphData.length number of entries, but only one graphColor variable to hold the color. Your code samples don't look complete so I'll make some assumptions about how the surrounding code must be. I recommend building up your series data in the for-loop directly so you can just use it in the Highcharts.chart call. The code is easier to read that way and probably more flexible too if you need to have more data rows.
// build the series data array here so it's simple to use in the chart call
const series = new Array(graphData.length);
for (let i = 0; i < graphData.length; i++) {
let graphColor = "#000000"; // a default color just in case
// can use if/else or a switch here
if (graphData[i].title === "LOW") {
graphColor = "#0D6302";
} else if (graphData[i].title === "MEDIUM-LOW") {
graphColor = "#0B7070";
} else if (graphData[i].title === "MEDIUM") {
graphColor = "#DC9603";
} else if (graphData[i].title === "MEDIUM-HIGH") {
graphColor = "#DD5F0C";
} else if (graphData[i].title === "HIGH") {
graphColor = "#C50710";
}
series[i] = {
name: graphData[i].title,
color: graphColor,
data: [graphData[i].result]
};
}
// Adjust the series data as needed
series[1].showInLegend = false;
series[1].linkedTo = ":previous";
Highcharts.chart("container", {
chart: { type: "bar" },
title: { text: "Bar Graph" },
xAxis: {},
yAxis: {
min: 0,
formatter: function() {
return this.value + "%";
},
title: { text: "% of Total" }
},
legend: { reversed: false },
plotOptions: { series: { stacking: "normal" } },
series: series
});
Not sure if I've properly understood what are you trying to do, but try this way:
const colorMap = { "LOW":"#0D6302",
"MEDIUM-LOW": "#0B7070",
"MEDIUM": "#DC9603",
"MEDIUM-HIGH": "#DD5F0C",
"HIGH":"#C50710"
}
...
series: [{
name: `graphData[0].title`,
color: colorMap[graphData[0].title],
data: [graphData[0]],
}, {
In the Highchart way - you can iterate through the series after chart initialization and set the wanted colors by particular series.
Demo: https://jsfiddle.net/BlackLabel/6hm4ebna/
chart: {
type: 'bar',
events: {
load() {
let chart = this;
chart.series.forEach(s => {
console.log(s)
if (s.name === 'test1') {
s.update({
color: 'red'
})
}
else if (s.name === 'test3') {
s.update({
color: 'green'
})
}
})
}
}
},
API: https://api.highcharts.com/highcharts/chart.events.load
If this wouldn't help please reproduce your attempt with the sample data on the online editor which I could work on.
the custom SVG marker symbol I have drawn is rendered differently in the legend than in the chart. I have drawn the marker that I need for the chart but in the legend, the symbol has a thin line to the left.
I have attached a picture below and will include the code, I have spent too much time on this and don't have anyone to ask on this topic. If anyone can help me out, it would be greatly appreciated.
function renderChart(data, startRange, endRange) {
// Create custom marker
Highcharts.SVGRenderer.prototype.symbols.lineBar = function (x, y, w, h) {
return ['M', x + w / 2, y + h / 2, 'L', x + w + 10, y + h / 2, 'z'];
};
if (Highcharts.VMLRenderer) {
Highcharts.VMLRenderer.prototype.symbols.lineBar = Highcharts.SVGRenderer.prototype.symbols.lineBar;
}
var chart = Highcharts.chart({
chart: {
renderTo: 'system-load-scheduler',
type: 'line',
},
navigation: {
buttonOptions: {
enabled: false
}
},
title: {
text: ''
},
yAxis: {
min: 0,
title: {
text: 'Tasks'
},
labels: {
style: {
color: 'blue'
}
},
categories: generateCategories(data),
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
day: '%b %d'
},
title: {
text: 'Date'
}
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: 'Scheduled {point.x:%b. %e} at {point.x:%l:%M%P}'
},
plotOptions: {
line: {
marker: {
enabled: true
}
},
series: {
cursor: 'pointer',
stickyTracking: false,
marker: {
states: {
hover: {
radiusPlus: 0,
lineWidthPlus: 1,
halo: {
size: 0
}
}
}
},
states: {
hover: {
halo: {
size: 0
}
}
}
}
},
legend: {
enabled: true,
symbolPadding: 20
},
series: generateSeries(data, startRange, endRange)
});
chart.yAxis[0].labelGroup.element.childNodes.forEach(function (label) {
label.style.cursor = 'hand';
label.onclick = function () {
var idx = ctrl.allTaskNames.indexOf(this.textContent);
renderTaskInfo(ctrl.data[idx]);
ctrl.scheduler.taskIdx = idx;
ctrl.backService.saveObject(CTRL_DASHBOARD_SCHEDULER_STR, ctrl.scheduler);
};
});
return chart;
}
You can erase the line with just some CSS code
.highcharts-legend .highcharts-graph {
display:none;
}
Fiddle
I'm using flotCharts and when i use two or more bar graphs, on hovering the bar it shows the value of the last graph loaded only, and the other graphs get the same value of the first. Here is the code:
HTML:
<div class="flot-chart">
<div class="flot-chart-content" id="flot-chart-#ControlID"></div>
</div>
JavaScript:
var series_#ControlID = [
#foreach (var serie in Model.Series)
{
<text>
{
label: '#serie.Name',
#DisplayGraphType(serie)
data: [
#foreach (var point in serie)
{
<text>
[#point.Item1, #point.Item2],
</text>
}
]
},
</text>
}
];
var xlabels = [
#foreach (var lbl in Model.Labels)
{
<text>[#lbl.Item1, "#lbl.Item2"],</text>
}
];
function getLabel(xval) {
var lbl = xval;
xlabels.forEach(function(e){
console.log(parseInt(e[0]) == parseInt(xval));
if (parseInt(e[0]) == parseInt(xval)) {
lbl = e[1];
}
});
return lbl;
}
$(function () {
$.plot($("#flot-chart-#ControlID"), series_#ControlID, {
series: {
lines: {
lineWidth: 2,
fill: #((Model.Series.Count() == 1).ToString().ToLower()),
},
bars: {
barWidth: 0.6,
align: "center"
},
points: {
fill: #((Model.Series.Count() == 1).ToString().ToLower()),
}
},
xaxis: {
ticks: xlabels,
tickDecimals: 0
},
colors: #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.Series.Select(o => o.Color).ToArray())),
grid: {
color: "#999999",
hoverable: true,
clickable: true,
borderWidth: 0,
},
legend: {
show: true
},
tooltip: true,
tooltipOpts: {
content: function(label, xval, yval) {
var content = getLabel(xval) + ": " + yval;
return content;
},
}
});
});
the
#ControlID value is a Guid and it is automatically generated randomly and it's always different between charts.
In the example below, when i hover to the second bar of the graph, it shows the second bar value of the other graph (only the xaxes is wrong):
I fixed it, the problem was that i was overwriting the same variable because i included them more than once for each graph. The solution is to change the method names to make them unique using he IDs, as Raidri said in the comments:
var series_#ControlID = [
#foreach (var serie in Model.Series)
{
<text>
{
label: '#serie.Name',
#DisplayGraphType(serie)
data: [
#foreach (var point in serie)
{
<text>
[#point.Item1, #point.Item2],
</text>
}
]
},
</text>
}
];
var xlabels_#ControlID = [
#foreach (var lbl in Model.Labels)
{
<text>[#lbl.Item1, "#lbl.Item2"],</text>
}
];
function getLabel_#(ControlID)(xval) {
var lbl = xval;
xlabels_#(ControlID).forEach(function(e){
console.log(parseInt(e[0]) == parseInt(xval));
if (parseInt(e[0]) == parseInt(xval)) {
lbl = e[1];
}
});
return lbl;
}
$(function () {
$.plot($("#flot-chart-#ControlID"), series_#ControlID, {
series: {
lines: {
lineWidth: 2,
fill: #((Model.Series.Count() == 1).ToString().ToLower()),
},
bars: {
barWidth: 0.6,
align: "center"
},
points: {
fill: #((Model.Series.Count() == 1).ToString().ToLower()),
}
},
xaxis: {
ticks: xlabels_#ControlID,
tickDecimals: 0
},
colors: #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.Series.Select(o => o.Color).ToArray())),
grid: {
color: "#999999",
hoverable: true,
clickable: true,
borderWidth: 0,
#if (Model.LimitLine != null)
{
<text>
markings: [
{ color: '#000', lineWidth: 1, yaxis: { from: #Model.LimitLine, to: #Model.LimitLine }},
]
</text>
}
},
legend: {
show: true
},
tooltip: true,
tooltipOpts: {
content: function(label, xval, yval) {
var content = getLabel_#(ControlID)(xval) + ": " + yval;
return content;
},
}
});
});
I use date as a string in my chart.
How can I use my start-date and end-date string variables as a label in my xAxis?
start-date = '10.02.2013'
end-date = '10.05.2013'
The code and the chart image is attached. The only thing I need to do is to add startDateLabel and endDateLabel.
var dateEndLabel, dateStartLabel, i, j, lastDate, seriesData, x, y;
i = 0;
seriesData = new Array();
lastDate = data[i].Values.length - 1;
dateStartLabel = data[i].Values[0].Time;
dateEndLabel = data[i].Values[lastDate].Time;
while (i < data.length) {
seriesData[i] = [];
j = 0;
x = [];
y = [];
while (j < data[i].Values.length) {
x = data[i].Values[j].Time;
y = data[i].Values[j].Value;
seriesData[i].push([x, y]);
j++;
}
i++;
}
return $("#criticalWPtrend").highcharts({
chart: {
type: "line"
},
area: {
height: "100%",
width: "100%",
margin: {
top: 20,
right: 30,
bottom: 30,
left: 50
}
},
title: {
text: ""
},
subtitle: {
text: ""
},
legend: {
layout: "vertical",
verticalAlign: "right",
align: "right",
borderWidth: 0
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
day: '%m-%d'
},
tickInterval: 24 * 3600 * 1000
},
yAxis: {
title: {
text: 'Value'
},
lineWidth: 1,
min: 0,
minorGridLineWidth: 0,
gridLineWidth: 0,
alternateGridColor: null
},
tooltip: {
valueSuffix: " "
},
plotOptions: {
series: {
marker: {
enabled: false
},
stickyTracking: {
enabled: false
}
},
line: {
lineWidth: 2,
states: {
hover: {
lineWidth: 3
}
},
marker: {
enabled: false
}
}
},
series: [
{
name: data[0].Name,
data: seriesData[0]
}, {
name: data[1].Name,
data: seriesData[1]
}, {
name: data[2].Name,
data: seriesData[2]
}, {
name: data[3].Name,
data: seriesData[3]
}, {
name: data[4].Name,
data: seriesData[4]
}, {
name: data[5].Name,
data: seriesData[5]
}
],
navigation: {
menuItemStyle: {
fontSize: "10px"
}
}
});
});
Yes, this is possible with the renderer method. See this basic example.
chart.renderer.text('10.02.2013', 0, 300)
.attr({
rotation: 0
})
.css({
color: '#4572A7',
fontSize: '16px'
})
.add();
You are going to need to pay attention to the x/y locations (the 2 other params) to place it correctly. You can also modify the text styling.
I'm not sure, but i think you just need to update your xAxis by update method
this.xAxis[0].update({
title: {
text: "start-date = '10.02.2013' end-date = '10.05.2013'",
style: {
fontSize: '10px'
}
}
});
Here's example: http://jsfiddle.net/FEwKX/
But!
If your mean that the start and end dates need to tie to edges, you must specify xAxis settings in config
xAxis: {
categories: categoriesArray
}
where categoriesArray is array like this:
['10.02.2013', '', '', '', '', '', '', '', '', '', '', '10.05.2013']
It should be the same lenght as your lenght of series data.
Check out here: http://jsfiddle.net/FEwKX/1/
Hope that'll help you.
You can also use labelFormatter and http://api.highcharts.com/highcharts#xAxis.labels.formatter and check if labels isFirst or isLast then use your dates, in other cases return proper value (like number).