Custom tooltip or custom labels (chart.js 2)? - javascript

I need to get a chart like this and I have no idea how to get it.
I've tried with custom tooltips but I need show them all of them at the same time. I've tryed as well with chartjs-plugin-datalabels but the labels are inside the canvas and they appear cut.
Do I need to create a html tooltip for every data?
Any ideas?
Updated:
Here is my code:
options: {
responsive: true,
maintainAspectRatio: true,
legend: {
display: false
},
animation: {
animateScale: true,
animateRotate: true
},
cutoutPercentage: 60,
circumference: 2 * Math.PI,
showAllTooltips: true,
tooltips: {
enabled: false
},
plugins: {
datalabels: {
backgroundColor: function(context) {
return context.dataset.backgroundColor;
},
borderColor: 'white',
borderRadius: 50,
borderWidth: 1,
anchor: 'end',
align: 'end',
color: 'white',
padding: 10,
font: {
weight: 'normal',
size: '10'
},
formatter: function(value, context) {
var percentageNum = context.chart.data.datasets[0].data[context.dataIndex]
return percentageNum + '\n %';
}
}
}
}
and this is what I get:

Related

How to change labels axis position of dynamic data values that are showing around the chart. I'm using Highcharts here

I want to change the axis position of data label 6.02%. How do I change it because this data is dynamic. Here's my code :
Highcharts.chart('container' + this.random, {
credits: {
enabled: false
},
title: {
text: this.graphtitle,
align: 'left',
style: {
fontSize: '12px',
},
},
chart: {
height: this.graphheight,
width: 500,
animation: false,
backgroundColor: 'transparent',
},
plotOptions: {
pie: {
dataLabels: {
enabled: true,
color: '#000',
align: 'left',
format: '{point.y} %', // added percentage sign here
overflow: 'justify', // prevent labels from being cut off
distance: 10, // increase distance between labels
x: -40,
y: -20,
//css
style: {
fontSize: '10px',
textOutline: 0,
},
connectorWidth: 0,
},
animation: true,
showInLegend: true,
},
},
yAxis: {
labels: {
staggerLines: 2,
enabled: true,
align: 'left',
padding: 0,
reserveSpace: true
},
},
legend: {
layout: 'vertical',
verticalAlign: 'bottom',
align: 'right',
symbolHeight: 10,
symbolRadius: 0,
symbolPadding: 1,
itemMarginTop: 10,
itemMarginBottom: 5,
textOutline: 0,
itemStyle: {
fontSize: '10px',
textOutline: 0,
}
},
series: [{
enableMouseTracking: false,
type: 'pie',
innerSize: '65%',
colors: this.graphcolors,
data: this.graphdata,
},],
});
},
below is the visual of pie chart:
I was trying this method but it's not working with my code any other method anyone would like to suggest ?
chart.series[0].data[1].update({
dataLabels: {
align: 'center',
verticalAlign: 'middle',
inside: true
}
});
I suppose graphdata here is dynamic data passed as a props. I came across a similar kind of bottleneck recently.
What I did to resolve this error is following:
You can sort your data ascending or descending using life cycle hooks e.g. getting the highest value element at 0 index or getting the lowest value element at 0 index.
data property of series in high charts expects a object with name and other custom properties to app where graph data has values like
['value 1', 1],
['value 2', 2]
{
                  name: this.graphdata[0][0],
                  y: this.graphdata[0][1],
                  sliced: false,
                  selected: true,
                  dataLabels: {
                    x: -25,
                    y: -15
                  }
                },
               {
               name: this.graphdata[1][0],
               y: this.graphdata[1][1],
               sliced: false,
               selected: true,
               dataLabels: {
                 x: -60,
                y: -25
               }
},
  this.graphdata[2],
   ],`enter code here`
In your code, you put negative values for plotOptions.pie.dataLabels.x and plotOptions.pie.dataLabels.y. This is probably not the best strategy if you push data dynamically...
When you use setData() to update your series, Highcharts optimizes labels position automatically.
Here is a simple example:
let chart = Highcharts.chart('container', {
chart: {
type: 'pie'
},
plotOptions: {
pie: {
innerSize: '65%',
dataLabels: {
format: '{point.y}',
distance: 10
}
}
},
series: [{
colors: ['red', 'green', 'blue'],
data: [10, 20, 15]
}]
});
function getInt() {
return chance.integer({ min: 1, max: 100 });
}
document.querySelector('button').addEventListener('click', () => {
chart.series[0].setData([getInt(), getInt(), getInt()]);
});
#container {
width: 350px;
height: 350px;
}
<script src="https://code.highcharts.com/10.3.3/highcharts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chance#1.1.9/chance.min.js"></script>
<div id="container"></div>
<button type="button">Update</button>

Apex Charts donut chart - padding between series items in plot

I am attempting to create a donut chart in apex charts similar to the one shown below (right), I have gotten pretty close, however I need to have some stroke or padding around the series items along the plot of the donut chart as shown.
current configuration
const options = {
chart: {
type: 'donut',
height: 150,
width: '100%',
offsetX: 50
},
plotOptions: {
pie: {
startAngle: 10,
donut: {
size: '90%',
dataLabels: {
enabled: false
},
labels: {
show: true,
name: {
show: true,
offsetY: 38,
formatter: () => 'Completed'
},
value: {
show: true,
fontSize: '48px',
fontFamily: 'Open Sans',
fontWeight: 500,
color: '#ffffff',
offsetY: -10
},
total: {
show: true,
showAlways: true,
color: '#BCC1C8',
fontFamily: 'Open Sans',
fontWeight: 600,
formatter: (w) => {
const total = w.globals.seriesTotals.reduce(
(a, b) => a + b,
0
);
return `${total}%`;
}
}
}
}
},
},
dataLabels: {
enabled: false
},
labels: ['Completed', 'Cancelled', 'Pending', 'Failed'],
legend: {
show: false,
position: 'right',
offsetX: -30,
offsetY: 70,
formatter: (value, opts) => {
return value + ' - ' + opts.w.globals.series[opts.seriesIndex];
},
markers: {
onClick: undefined,
offsetX: 0,
offsetY: 25
}
},
fill: {
type: 'solid',
colors: ['#8BD742', '#BCC1C8', '#78AEFF', '#F74D52']
},
stroke: {
width: 0
},
colors: ['#8BD742', '#BCC1C8', '#78AEFF', '#F74D52']
};
Try setting the stroke width to greater than 0 and give the stroke same color as the background.
stroke: {
width: 4,
colors: ['#1E252A']
}

charts.js: how to get the legend colors of the labels

I am recieving in the context of my canvas (in ANGULAR 9) the information using:
var ctx = this.Chart.nativeElement.getContext('2d');
I would like to get to the legend colors which is generated automatically for chart.js
My canvas code is:
<canvas
baseChart
#linechart
id="linechart"
name="linechart"
[datasets]="grafica.series"
[labels]="grafica.labels"
[options]="lineChartOptions"
[colors]="lineChartColors"
[legend]="lineChartLegend"
[chartType]="lineChartType"
[plugins]="lineChartPlugins"
chart-dataset-override="dataSetOverride"
>
</canvas>
And options keeped in lineChartOptions:
{
responsive: true,
maintainAspectRatio: true,
// We use these empty structures as placeholders for dynamic theming.
scales: {
yAxes: [{
ticks: {
fontColor: "white",
fontSize: 8,
autoSkip: true,
maxTicksLimit: 5, //5 //responsivemode
beginAtZero: true
},
gridLines: {
color: 'rgba(222,222,222,0,3)',
lineWidth: 1
},
scaleLabel: {
display: true,
labelString: ejeYLabel,
fontColor: 'rgba(255,255,255,1)',
fontSize: 9
}
}],
xAxes: [{
ticks: {
fontColor: "white",
fontSize: 9,
stepSize: 1,
beginAtZero: true,
},
gridLines: {
color: 'rgba(222,222,222,0.3)',
lineWidth: 1
}
}]
},
legend: {
display: false, //false, //responsivemode
labels: {
fontColor: 'white' //set your desired color
},
position: 'bottom',
align: 'start',
},
plugins: {
datalabels: {
anchor: 'end',
align: 'end',
color: 'white',
formatter: function(value, context) {
return "";
}
}
}
}
Okey you can intercept the automated legend label creation call, and save the results somewhere before returning it, which gives you the colors.
change your labels block to this, and you can see in the console log how it looks:
legend: {
labels: {
fontColor: 'white', //set your desired color
generateLabels: (ctx) => {
var labels = Chart.defaults.global.legend.labels.generateLabels(ctx);
console.log('created labels', labels);
return labels;
}
}
},

Highcharts angular wrapper labels.items don't refresh

I'm using angular6 and the office highcharts angular wrapper (https://github.com/highcharts/highcharts-angular) in version 2.4.0.
Everything is working good except the labels that can be placed manually on the chart.
I just don't manage to get them refreshed.
I have a graph that can be filtered through the back-end. When I get the new generated data I update the data in my chartOptions which are used in the html as [options]="chartOptions" for the angular component.
The chartOptions are instanciated from my default class like this: this.chartOptions = new GraphConfigSeqAtteptedVsAchived().chartOptions;
The Class looks like this:
`import * as Highcharts from 'highcharts';
export class GraphConfigSeqAtteptedVsAchived{
public chartOptions: any;
constructor(){
this.chartOptions = {
chart: {
height: 600,
width: 620,
events:{load: function(){
this.myTooltip = new Highcharts.Tooltip(this, this.options.tooltip);
}
},
backgroundColor: 'transparent',
},
credits: {
text: 'charname',
href: ''
},
labels: {
},
exporting:{
chartOptions:{
title: {
text:'not set',
style:{
color: '#000000'
},
margin: 0
}
}
},
tooltip: {
enabled: false
},
xAxis: {
min: -10,
max: 0,
width: 535,
title: {
text: 'Rainfall (mm)',
style: {
fontWeight: "bold",
color: '#000000'
}
},
reversed: true,
tickInterval: 1
},
yAxis: {
min: -10,
max: 0,
title: {
text: 'Rainfall (mm)',
style: {
fontWeight: "bold",
color: '#000000'
}
},
reversed: true,
tickInterval: 1
},
title: {
text: ' as',
margin: 0,
style:{
color: 'transparent'
}
},
legend: {
layout: 'vertical',
align: 'left',
verticalAlign: 'top',
x: 100,
y: 90,
floating: true,
backgroundColor: '#FFFFFF',
borderWidth: 1,
navigation: {
enabled: false
}
},
plotOptions: {
scatter: {
stickyTracking: false,
allowPointSelect: true,
marker: {
radius: 3,
states: {
hover: {
enabled: true,
lineColor: 'rgb(100,100,100)'
}
}
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '',
hideDelay: 500
},
symbol: "circle",
events: {
mouseOut: function() {
this.chart.myTooltip.hide();
this.chart.myTooltip.options.enabled = false;
},
mouseOver: function() {
if(this.halo) {
this.halo.attr({
'class': 'highcharts-tracker'
}).toFront();
}
},
click: function(event) {
this.chart.myTooltip.options.enabled = true;
this.chart.myTooltip.refresh(event.point, event);
}
}
},
line:{
events: {
legendItemClick: function () {
return false;
}
}
},
series:{
allowPointSelect: true
}
},
series: [{
type: 'line',
data: [[30, 30], [-30, -30]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 1
}
},
showInLegend: false,
color: "rgba(0, 0, 0, 0.6)",
enableMouseTracking: false
},{
type: 'line',
data: [[30, 29.5], [-29.5, -30]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 0
}
},
showInLegend: false,
dashStyle: 'ShortDash',
color: "rgba(125, 162, 159, 0.35)",
enableMouseTracking: false
},{
type: 'line',
data: [[29.5, 30], [-30, -29.5]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 0
}
},
showInLegend: false,
dashStyle: 'ShortDash',
color: "rgba(125, 162, 159, 0.35)",
enableMouseTracking: false
},{
type: 'line',
data: [[29, 30], [-30, -29]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 0
}
},
showInLegend: false,
dashStyle: 'ShortDash',
color: "rgba(197, 144, 161, 0.35)",
enableMouseTracking: false
},{
type: 'line',
data: [[30, 29], [-29, -30]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 0
}
},
showInLegend: false,
dashStyle: 'ShortDash',
color: "rgba(197, 144, 161, 0.35)",
enableMouseTracking: false
}]
}
}
}`
The generated data is in the typescript dynamically added and all of that works just fine. Everything is refreshed after I set the updateFlag for [(update)]="updateGraph". The axis titles are also fine.
The only thing that's not refreshed for me are the labels i dynamically added to the chart like this:
let labelTotalNumberOfEyes = {
html : this.translate.instant('GRAPHS.TOTAL_NUMBER_OF_EYES') + ': ' + (scatterSeries.data.length + scatterSeriesRetreatment.data.length),
style : {
left : '330px',
top : '368px',
fontSize : '14px',
backgroundColor: '#FFFFFF',
borderWidth: 1,
}
}
this.chartOptions.labels.items.push(labelTotalNumberOfEyes);
Does someone have any idea what I'm might doing wrong? I don't see any further option than just setting this update flag and it works fine for everything but the labels.
Please let me know if you're missing any information.
Thanks in advance.
This issue is actually a Highcharts bug. I've reported it here: https://github.com/highcharts/highcharts/issues/10429.
As a workaround, you can use Highcharts.SVGRenderer to add a custom label and store reference to it in your component. Next, when updating, call attr() method on the label (Highcharts.SVGElement) and set new options. Check demo and code posted below.
Add a label on chart callback:
constructor() {
const self = this;
this.chartCallback = chart => {
self.chart = chart;
self.label = chart.renderer
.text("test", 100, 100)
.css({
fill: "#555",
fontSize: 16
})
.add()
.toFront();
};
}
call attr() on the label while updating:
update_chart() {
const self = this,
chart = this.chart;
chart.showLoading();
setTimeout(() => {
chart.hideLoading();
self.chartOptions.series = [
{
data: [10, 25, 15],
name: "updatedSerieName"
}
];
self.chartOptions.yAxis.title.text = "updatedData";
self.label
.attr({
text: "test1",
x: 150,
y: 120
})
.css({
fill: "red",
fontSize: 20
});
self.updateFromInput = true;
}, 2000);
}
Demo:
https://codesandbox.io/s/8zo0yvqqwj
API reference:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text
https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr

JQuery flot remove bar border

Here's my jsFiddle
How can I remove the border or to be the same as the bar (not darker) ?
EDIT: Actually, I need to remove the border completely. Is this possible?
var chartOptions = {
xaxis: { ticks: chartTicks },
grid: { clickable: true, hoverable: true },
series: { stack: true, bars: { fill: '#000', show: true, align:'center', barWidth: 0.5 } }
};
You can use the lineWidth option to remove the outline / border of the bars and / or the fillColor option to change the filling (this can also be used for gradients):
series: {
stack: true,
bars: {
show: true,
align: 'center',
barWidth: 0.5,
lineWidth: 0,
fillColor: {
colors: [{
opacity: 1.0
}, {
opacity: 1.0
}]
}
}
}
See this fiddle for an example.
To remove the border from the bars in the graph, you can add lineWidth: 0 to the bars object in your options.
series: {
stack: true,
bars: {
lineWidth: 0,
show: true,
align: 'center',
barWidth: 0.5
}
}
Here it is in action.
This could be found in the API docs here, by the way.
I am not 100% sure if you want to remove borders around the graph or the bars. The jsFiddle here has done both and the code is explained below.
To remove the border around the bars. Supply lineWidth to the bars as in the example below.
var chartOptions = {
xaxis: {
ticks: chartTicks
},
grid: {
clickable: true,
hoverable: true
},
series: {
stack: true,
bars: {
show: true,
align: 'center',
barWidth: 0.5,
lineWidth: 0
}
}
};
To remove the border from around the graph. Supply borderWidth to the grid you can set borderWidth: 0 or you can specify each width like in the example below.
var chartOptions = {
xaxis: {
ticks: chartTicks
},
grid: {
clickable: true,
hoverable: true,
borderWidth: {
top: 0,
right: 0,
bottom: 0,
left: 0
}
},
series: {
stack: true,
bars: {
show: true,
align: 'center',
barWidth: 0.5
}
}
};

Categories

Resources