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) + "%"
}
}
}
Related
I am trying to make a gradient line chart, The issue is with tooltip legend color and color of data points, they appear in brown gradient which was the default.
I was able to change the tooltip color, anyhow that is not the actual data point color but able to fix it to one color at least. whereas the points on the line do not pick up the color of the line.
Can someone point me in right direction?
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};
var option;
var data = [["2020-06-05",116],["2020-06-06",129],["2020-06-07",135],["2020-06-08",86],["2020-06-09",73],["2020-06-10",85],["2020-06-11",73],["2020-06-12",68],["2020-06-13",92],["2020-06-14",130],["2020-06-15",245],["2020-06-16",139],["2020-06-17",115],["2020-06-18",111],["2020-06-19",309],["2020-06-20",206],["2020-06-21",137],["2020-06-22",128],["2020-06-23",85],["2020-06-24",94],["2020-06-25",71],["2020-06-26",106],["2020-06-27",84],["2020-06-28",93],["2020-06-29",85],["2020-06-30",73],["2020-07-01",83],["2020-07-02",125],["2020-07-03",107],["2020-07-04",82],["2020-07-05",44],["2020-07-06",72],["2020-07-07",106],["2020-07-08",107],["2020-07-09",66],["2020-07-10",91],["2020-07-11",92],["2020-07-12",113],["2020-07-13",107],["2020-07-14",131],["2020-07-15",111],["2020-07-16",64],["2020-07-17",69],["2020-07-18",88],["2020-07-19",77],["2020-07-20",83],["2020-07-21",111],["2020-07-22",57],["2020-07-23",55],["2020-07-24",60]];
var dateList = data.map(function (item) {
return item[0];
});
var valueList = data.map(function (item) {
return item[1];
});
option = {
color: {
type: 'linear',
x: 0, y: 1,x2:0,y2:0,
colorStops: [{
offset: 0, color: '#00d4ff' // color at 0% position
}, {
offset: 1, color: '#090979' // color at 100% position
}],
global:true
},
// Make gradient line here
visualMap: [{
show: true,
type: 'continuous',
seriesIndex: 0,
min: 0,
max: 400
}],
title: [{
left: 'center',
text: 'Gradient along the y axis'
}],
xAxis: [{
data: dateList,
axisPointer: {
label:{
color:['#5470c6'],
}
},
axisLabel: {
formatter: function (value) {
return moment(value).format("MMM YY");
// And other formatter tool (e.g. moment) can be used here.
}
}
}],
yAxis: [{
type: 'value',
axisPointer: {
label:{
color:['#5470c6'],
}
}
}],
grid: [{
width:'auto',
height:'auto'
}],
tooltip : {
trigger: 'axis',
axisPointer: {
animation: true,
},
formatter: function (params) {
var colorSpan = color => '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:' + color + '"></span>';
let rez = '<p>' + params[0].axisValue + '</p>';
console.log(params); //quite useful for debug
params.forEach(item => {
// console.log(item); //quite useful for debug
var xx = '<p>' + colorSpan('#00d4ff') + ' ' + item.seriesName + ': ' + item.data + '</p>'
rez += xx;
});
console.log(rez);
return rez;
}
},
series: [{
color:['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'],
type: 'line',
showSymbol: false,
data: valueList,
// smooth: true,
label:{
show:true,
position:'top'
},
lineStyle:{
color: {
type: 'linear',
x: 0, y: 1,x2:0,y2:0,
colorStops: [{
offset: 0, color: '#00d4ff' // color at 0% position
}, {
offset: 1, color: '#090979' // color at 100% position
}],
global:false
}
}
}]
};
console.log(myChart);
if (option && typeof option === 'object') {
myChart.setOption(option);
}
You need to add gradientColor array to echarts options. Now echart will take care of changing color of tooltip and data point. You can also remove your custom tooltip formatted function.
gradientColor: ["#00d4ff", "#090979"]
Here the complete options object:
var data = [];
var dateList = data.map(function(item) {
return item[0];
});
var valueList = data.map(function(item) {
return item[1];
});
option = {
gradientColor: ["#00d4ff", "#090979"],
// Make gradient line here
visualMap: [
{
show: true,
type: "continuous",
seriesIndex: 0,
min: 0,
max: 400
}
],
title: [
{
left: "center",
text: "Gradient along the y axis"
}
],
xAxis: [
{
data: dateList,
axisPointer: {
label: {
color: ["#5470c6"]
}
},
axisLabel: {
formatter: function(value) {
return moment(value).format("MMM YY");
// And other formatter tool (e.g. moment) can be used here.
}
}
}
],
yAxis: [
{
type: "value",
axisPointer: {
label: {
color: ["#5470c6"]
}
}
}
],
grid: [
{
width: "auto",
height: "auto"
}
],
tooltip: {
trigger: "axis",
axisPointer: {
animation: true
}
},
series: [
{
type: "line",
showSymbol: false,
data: valueList,
// smooth: true,
label: {
show: true,
position: "top"
}
}
]
};
$('#container').bind('mousemove touchmove touchstart', function (e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent);
point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
});
Highcharts.Pointer.prototype.reset = function () {
return undefined;
};
Highcharts.Point.prototype.highlight = function (event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function (chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(
e.min,
e.max,
undefined,
false,
{ trigger: 'syncExtremes' }
);
}
}
});
}
}
// Get the data. The contents of the data file can be viewed at
$.getJSON(
'https://cdn.rawgit.com/highcharts/highcharts/v6.0.4/samples/data/activity.json',
function (activity) {
$.each(activity.datasets, function (i, dataset) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function (val, j) {
return [activity.xData[j], val];
});
$('<div class="chart">')
.appendTo('#container')
.highcharts({
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20
},
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} km'
}
},
yAxis: {
title: {
text: null
}
},
tooltip: {
positioner: function () {
return {
// right aligned
x: this.chart.chartWidth - this.label.width,
y: 10 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
}
);
Any help will be appreciated
You can hide unwanted x axes using visible property:
xAxis: {
visible: i === 2,
(...)
},
Live demo: http://jsfiddle.net/BlackLabel/abf07jgc/
API reference: https://api.highcharts.com/highcharts/xAxis.visible
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 want to add data tables to Charts.
I tried the implementation shown here: http://jsfiddle.net/highcharts/z9zXM/
but it didnt work for me.
I suspect its because how I instantiate highcharts.
in the example above the chart is generated by instantiating the Highcharts object.
my code:
// data from an ajax call
$.each(data, function(indicator, questions) {
indicator_type = "";
$.each(questions, function(question, value) {
dataChartType = "column";
series = [];
categories = [];
category_totals = {};
if(value.programs == null) {
return true;
}
$.each(value.programs, function(program, body) {
total = 0;
values = [];
$.each(body, function(j, k) {
if (categories.indexOf(j) == -1) {
categories.push(j);
category_totals[j] = 0;
}
if(k != 0) {
values.push(k);
} else {
values.push(null);
}
category_totals[j] += parseInt(k, 10);
total += k;
});
series.push({
data: values,
total: total,
name: program //question
});
}); // eo each program
var chartDiv = document.createElement('div');
chartDiv.className = "chart";
$('.charts_wrap').append(chartDiv);
$(chartDiv).highcharts({
events: {
load: Highcharts.drawTable
},
chart: {
type: dataChartType
},
xAxis: {
categories: categories
},
legend: {
layout: 'vertical',
backgroundColor: '#FFFFFF',
align: 'right',
verticalAlign: 'top',
y: 60,
x: -60
},
tooltip: {
formatter: function () {
return '<strong>' + this.series.name + '</strong><br/>' + this.x + ': ' + this.y;
}
},
plotOptions: {
line: {
connectNulls: true
},
column: {
stacking: 'normal',
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px w'
}
}
}
},
series: series,
title:{ text: indicator },
subtitle:{ text: question }
});
}); // EO each question
}); // eo each indicator
When instantiating highcharts like this:
$("#container").highcharts({ ...
The events option needs to be included inside the charts option:
$("#container").highcharts({
chart: {
type: 'column',
events: {
load: Highcharts.drawTable
},
},
...
Not sure why because I have done it in the past, but I have a Highcharts bar chart and it won't animate. This is the declaration of the chart,
function initializeData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push({
name: setName($scope.jsondata[x].name),
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 5000);
}
function updateData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
console.debug("here");
for (x = 0; x < 5; x++) {
$scope.chart.series[0].data[x].update({
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'category',
labels: {
style: {
fontSize: '11px'
}
}
},
yAxis: {
min: 0,
max: 100,
title: {
text: 'Total Score',
align: 'high'
}
},
legend: {
enabled: false
},
tooltip: {
pointFormat: 'Total Score <b>{point.y:.3f}</b>'
},
series: [{
name: 'Active Users',
data: [],
dataLabels: {
enabled: true,
rotation: 30,
style: {
fontSize: '10px',
fontFamily: 'Verdana, sans-serif'
},
format: '{point.y:.3f}', // one decimal
}
}]
});
And as you can see I have animate : true, so I am not sure what is the problem here. I have this older plunker where all of the data is in separate series, but it animates fine. But this is the plunker I am working on and having trouble with. They are like identical basically. In the newer one I broke out the initialization of data into its own method, but that is the only real main difference.
Some edits:
So as I was saying, I have done things this way with an areaspline chart (I know it was said they work a bit different but they are set up identically).
function initializeData() {
$interval.cancel(mainInterval);
$scope.previousPackets = '';
$http.get("https://api.myjson.com/bins/nodx").success(function(returnedData) {
var newdata = [];
var x = (new Date()).getTime();
for (var step = 9; step >= 0; step--) {
newdata.push([x - 1000 * step, 0]);
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 2000);
}
function updateData() {
$http.get(url + acronym + '/latest').success(function(returnedData) {
var x = (new Date()).getTime();
if ($scope.previousPackets != returnedData[0].numPackets) {
$scope.chart.series[0].addPoint([x, returnedData[0].numPackets], true, true);
$scope.previousPackets = returnedData[0].numPackets;
} else {
$scope.chart.series[0].addPoint([x, 0], true, true);
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'areaspline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Packets'
},
plotLines: [{
value: 0,
width: 1,
color: '#d9534f'
}]
},
tooltip: {
formatter: function() {
return Highcharts.numberFormat(this.y) + ' packets<b> | </b>' + Highcharts.dateFormat('%H:%M:%S', this.x);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Packets',
data: []
}]
});
I also updated the first chunk of code with the initializeData() method and updateData() method which are seemingly identical in both different charts.
It looks like it plays an important role if you provide your data at chart initialization or after. For simplicity I refactored your code a little
function initializeChart(initialData, onload) {
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: onload
}
....
series: [{
name: 'Active Users',
data: initialData,
dataLabels: {
enabled: true,
format: '{point.y:.3f}', // one decimal
}
}]
});
}
function getData(callback) {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push([setName(ret[x].name), ret[x].data]);
}
callback(newdata);
});
}
As a result your two planks are in essense reduced to two methods below. The first initializes chart with preloaded data and the second updates data in existing chart.
function readDataFirst() {
getData(function(newdata) {
initializeChart(newdata);
});
}
function initializeChartFirst() {
initializeChart([], function() {
getData(function(newdata) {
$scope.chart.series[0].setData(newdata);
})
});
}
The first one animates fine while the second does not. It looks like highcharts skips animation if dataset is not initial and is treated incompatible.
However if you really want to have animation in your current plant (chart first workflow) you can achieve that by initializing first serie with zeros and then with the real data. This case it will be treated as update
function forceAnimationByDoubleInitialization() {
getData(function(newdata) {
initializeChart([]);
var zerodata = newdata.map(function(item) {
return [item[0], 0]
});
$scope.chart.series[0].setData(zerodata);
$scope.chart.series[0].setData(newdata);
});
All these options are available at http://plnkr.co/edit/pZhBJoV7PmjDNRNOj2Uc