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
Related
I'm using highcharts to create a master-detail chart, could you help me how to add another series type area to the chart? i have used example from official site, but i cant imagine how to add second area to this chart
const priceChart1 = Highcharts.getJSON(
'https://cdn.jsdelivr.net/gh/highcharts/highcharts#v7.0.0/samples/data/usdeur.json',
data => {
let detailChart;
// create the detail chart
function createDetail(masterChart) {
// prepare the detail chart
var detailData = [],
detailStart = data[0][0];
masterChart.series[0].data.forEach(point => {
if (point.x >= detailStart) {
detailData.push(point.y);
}
});
// create a detail chart referenced by a global variable
detailChart = Highcharts.chart('detail-container', {
chart: {
zoomType: "x",
spacingLeft: 10,
spacingRight: -20,
borderRadius: 10,
backgroundColor: "#F3F3F3",
borderColor: "#335cad",
height: priceChartHeight,
style: { fontFamily: "Manrope" },
style: {
position: 'absolute'
},
resetZoomButton: {
position: {
// align: 'right', // by default
// verticalAlign: 'top', // by default
x: -40,
y: 5
},
theme: {
fill: '#377DED',
stroke: 'transparent',
r: 0,
style: {
color: 'white',
borderRadius: 10
},
states: {
hover: {
fill: '#41739D',
style: {
color: 'white'
},
},
},
},
},
marginBottom: 90,
reflow: false,
marginLeft: 10,
style: {
position: 'absolute'
}
},
credits: {
enabled: false
},
title: {
text: null,
align: 'left'
},
subtitle: {
text: null,
align: 'left'
},
xAxis: {
type: 'datetime',
visible: false,
},
yAxis: {
title: {
text: null,
},
opposite: true,
gridLineColor: "rgba(87, 87, 87, 0.15)",
gridLineDashStyle: "dash",
left: -40
},
tooltip: {
formatter: function () {
var point = this.points[0];
return '' + '<br/>' + ' <span style="font-weight: 700;font-size: 14px; line-height: 19px; color: #377DED;"> ' + Highcharts.numberFormat(point.y, 2) + '</span> ' + '<span style="font-size: 9px; font-weight: 300; line-height: 12px; color: rgba(51,51,51, 0.25)">Nominal</span>' + '<br/> ' + '<span style="font-size: 9px; font-weight: 300; line-height: 12px; color: rgba(51,51,51, 0.25)">' + Highcharts.dateFormat('%e %B %Y', this.x) + '</span>' },
shared: true,
borderRadius: 5,
borderColor: 'transparent',
shadow: false,
backgroundColor: '#fff'
},
legend: {
enabled: false
},
plotOptions: {
series: {
marker: {
enabled: false,
states: {
hover: {
enabled: true,
radius: 3
}
}
}
}
},
series: [
{
name: 'Nominal',
data: detailData,
type: 'area',
},
],
exporting: {
enabled: false
}
}); // return chart
}
// create the master chart
function createMaster() {
Highcharts.chart('master-container', {
chart: {
reflow: false,
borderWidth: 0,
backgroundColor: null,
spacingLeft: 10,
spacingRight: 30,
borderRadius: 10,
zoomType: 'x',
events: {
// listen to the selection event on the master chart to update the
// extremes of the detail chart
selection: function (event) {
var extremesObject = event.xAxis[0],
min = extremesObject.min,
max = extremesObject.max,
detailData = [],
xAxis = this.xAxis[0];
// reverse engineer the last part of the data
this.series[0].data.forEach(point => {
if (point.x > min && point.x < max) {
detailData.push([point.x, point.y]);
}
});
// move the plot bands to reflect the new detail span
xAxis.removePlotBand('mask-before');
xAxis.addPlotBand({
id: 'mask-before',
from: data[0][0],
to: min,
color: 'rgba(0, 0, 0, 0)'
});
xAxis.removePlotBand('mask-after');
xAxis.addPlotBand({
id: 'mask-after',
from: max,
to: data[data.length - 1][0],
color: 'rgba(0, 0, 0, 0)'
});
xAxis.addPlotBand({
id: 'mask-after',
from: min,
to: max,
color: 'rgba(255, 255, 255, 1)',
borderColor: "#377DED",
borderWidth: 2
});
detailChart.series[0].setData(detailData);
console.log(min)
console.log(max)
return false;
}
}
},
title: {
text: null
},
accessibility: {
enabled: false
},
xAxis: {
type: "datetime",
labels: { format: '{value:%b %e }' },
crosshair: {
color: '#377DED80'
},
lineWidth: 0, minorGridLineWidth: 0, lineColor: 'transparent', minorTickLength: 0, tickLength: 0,
top: -5,
showLastTickLabel: true,
maxZoom: 14 * 24 * 3600000, // fourteen days
plotBands: [{
id: 'mask-before',
from: data[0][0],
to: data[data.length - 1][0],
color: 'rgba(0, 0, 0, 0)'
}],
title: {
text: null
},
},
yAxis: {
gridLineWidth: 0,
labels: {
enabled: false
},
title: {
text: null
},
min: 0.6,
showFirstLabel: false
},
tooltip: {
borderRadius: 50,
borderColor: 'red'
},
legend: {
enabled: false
},
credits: {
enabled: false
},
plotOptions: {
series: {
fillColor: {
linearGradient: [0, 0, 0, 70],
stops: [
[0, Highcharts.getOptions().colors[0]],
[1, 'rgba(255,255,255,0)']
]
},
lineWidth: 1,
marker: {
enabled: false
},
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
enableMouseTracking: false
}
},
series: [{
type: 'area',
name: 'USD to EUR',
pointInterval: 24 * 3600 * 1000,
pointStart: data[0][0],
data: data
}],
exporting: {
enabled: false
}
}, masterChart => {
createDetail(masterChart);
}); // return chart instance
}
// make the container smaller and add a second container for the master chart
const container = document.getElementById('price-chart-main');
container.style.position = 'relative';
container.innerHTML += '<div id="detail-container" style="height: 100%"></div><div id="master-container" style="height: 90px; position: absolute; bottom: 0; width: 100%"></div>';
// create master and in its callback, create the detail chart
createMaster();
}
);
there is example that i used https://www.highcharts.com/demo/dynamic-master-detail
Adding a new series to a master-detail chart is very simple. You need to only add a new data set and connect it to the right series. For example:
var detailData = [
[],
[]
],
detailStart = data1[0][0];
masterChart.series.forEach((s, index) => {
s.points.forEach(point => {
if (point.x >= detailStart) {
detailData[index].push(point.y);
}
});
});
// create a detail chart referenced by a global variable
detailChart = Highcharts.chart('detail-container', {
chart: {
type: 'area',
...
},
...,
series: [{
data: detailData[0]
}, {
data: detailData[1]
}]
});
Live demo: https://jsfiddle.net/BlackLabel/97dxakfe/
API Reference: https://api.highcharts.com/highcharts/series
Can we add class or change color of the title according to the from and to color values in gauge highcharts
I am working on the following code:
$('#container').highcharts({
chart: {
type: 'gauge',
borderWidth: 0,
},
title: {
useHTML: true,
verticalAlign: 'middle',
floating: false,
text: '<div style="text-align:center"><span class="gauge-count">80</span><span class="gauge-category-title">mg/L</span></div>'
},
pane: {
startAngle: -160,
endAngle: 160,
background: null
},
// the value axis
yAxis: {
min: 0,
max: 100,
minorTickPosition: 'inside',
minorTickColor: 'transparent',
tickPosition: 'inside',
tickColor: 'transparent',
labels: {
enabled: false
},
plotBands: [{
from: 0,
to: 30,
className: 'red-band'
}, {
from: 30,
to: 60,
className: 'yellow-band'
}, {
from: 60,
to: 100,
className: 'green-band'
}]
},
plotOptions: {
gauge: {
dataLabels: {
formatter: function() {
return null;
},
y: 80,
borderWidth: 0,
useHTML: false
},
}
},
series: [{
name: 'Speed',
data: [80]
}]
}, );
Live example: https://codepen.io/qadeershaikh/pen/MRmJwP?editors=0010
To dynamically set the chart's title color, you can use css method for SVG elements, for example in render event function:
chart: {
type: 'gauge',
borderWidth: 0,
events: {
render: function() {
var value = this.series[0].yData[0],
color;
if (value < 30) {
color = '#DF5353';
} else if (value < 60) {
color = '#DDDF0D';
} else {
color = '#55BF3B';
}
this.title.css({
color: color
});
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/fj7mLrxa/
API Reference:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGElement#css
Need help with highchartsJs. I need chart like on screenshots. For lines i found this, but not fully what i needed. For square i don't have any ideas. Square is most priority.
Any help will be appreciated. Thanks.
square
horizontal lines
If someone need something like this
https://jsfiddle.net/gdgb941o/20/
chart: {
type: 'column'
},
title: {
text: false
},
tooltip: {
enabled: false
},
credits: {
enabled: false
},
xAxis: {
tickWidth: 0,
lineWidth: 0,
type: 'category',
gridLineWidth: 0
},
yAxis: {
lineWidth: 0,
gridLineWidth: 0,
labels: {
enabled: false
},
max: 100,
title: {
text: false
}
},
navigation: {
buttonOptions: {
enabled: false
}
},
legend: {
enabled: false
},
plotOptions: {
column: {
borderWidth: 0,
grouping: false
},
series: {
}
},
series: [{
data: [{
borderWidth: 2,
borderColor:'#41bc9b',
color: 'white',
name: 'Yes',
y: 100,
dataLabels: {
formatter: function() {
return "33" + "%"
},
enabled: true,
inside: true,
align: 'center',
color: 'black',
style: {
fontSize: 20,
textOutline: false
}
}
}, {
borderWidth: 2,
borderColor:'#41bc9b',
color: 'white',
name: 'The email did not come',
y: 100,
dataLabels: {
formatter: function() {
return "80" + "%"
},
enabled: true,
inside: true,
align: 'center',
color: 'black',
style: {
fontSize: 20,
textOutline: false
}
}
}, {
borderWidth: 2,
borderColor:'#41bc9b',
color: 'white',
name: 'Error in verification',
y: 100,
dataLabels: {
formatter: function() {
return "55" + "%"
},
enabled: true,
inside: true,
align: 'center',
color: 'black',
style: {
fontSize: 20,
textOutline: false
}
}
},
{
borderWidth: 2,
borderColor:'#41bc9b',
color: 'white',
name: 'No',
y: 100,
dataLabels: {
formatter: function() {
return "20" + "%"
},
enabled: true,
inside: true,
align: 'center',
color: 'black',
style: {
fontSize: 20,
textOutline: false
}
}
}]
}, {
pointPadding: 0.125,
data: [{
color: '#41bc9b',
name: 'Yes',
y: 33
}, {
color: '#41bc9b',
name: 'The email did not come',
y: 80
}, {
color: '#41bc9b',
name: 'Error in verification',
y: 55
},
{
color: '#41bc9b',
name: 'No',
y: 20
}]
}]
I have created a Bar graph using echarts. I want to bind multiple values to data object dynamically, currently I'm able to bind only single value. here is my java script. I'mm a newbie for this, hoping for a fully functional solution.
var myChart = echarts.init(document.getElementById('page_views_today'));
var option = {
// Setup grid
grid: {
zlevel: 0,
x: 20,
x2: 40,
y: 20,
y2: 20,
borderWidth: 0,
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
},
// Add tooltip
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow', // line|shadow
lineStyle: { color: 'rgba(0,0,0,.5)', width: 1 },
shadowStyle: { color: 'rgba(0,0,0,.1)' }
}
},
// Add legend
legend: {
data: []
},
toolbox: {
orient: 'vertical',
show: true,
showTitle: true,
color: ['#bdbdbd', '#bdbdbd', '#bdbdbd', '#bdbdbd'],
feature: {
mark: { show: false },
dataZoom: {
show: true,
title: {
dataZoom: 'Data Zoom',
dataZoomReset: 'Reset Zoom'
}
},
dataView: { show: false, readOnly: true },
magicType: {
show: true,
itemSize: 12,
itemGap: 12,
title: {
line: 'Line',
bar: 'Bar',
},
type: ['line', 'bar'],
option: {
/*line: {
itemStyle: {
normal: {
color:'rgba(3,1,1,1.0)',
}
},
data: [1,2,3,4,5,6,7,8,9,10,11,12]
}*/
}
},
restore: { show: false },
saveAsImage: { show: true, title: 'Save as Image' }
}
},
// Enable drag recalculate
calculable: true,
// Horizontal axis
xAxis: [{
type: 'category',
boundaryGap: false,
data: [
'0h-2h', '2h-4h', '4h-6h', '6h-8h', '8h-10h', '10h-12h', '12h-14h', '14h-16h', '16h-18h', '18h-20h', '20h-22h', '22h-24h'
],
axisLine: {
show: true,
onZero: true,
lineStyle: {
color: 'rgba(63,81,181,1.0)',
type: 'solid',
width: '2',
shadowColor: 'rgba(0,0,0,0)',
shadowBlur: 5,
shadowOffsetX: 3,
shadowOffsetY: 3,
},
},
axisTick: {
show: false,
},
splitLine: {
show: false,
lineStyle: {
color: '#fff',
type: 'solid',
width: 0,
shadowColor: 'rgba(0,0,0,0)',
},
},
}],
// Vertical axis
yAxis: [{
type: 'value',
splitLine: {
show: false,
lineStyle: {
color: 'fff',
type: 'solid',
width: 0,
shadowColor: 'rgba(0,0,0,0)',
},
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
axisLine: {
show: false,
onZero: true,
lineStyle: {
color: '#ff0000',
type: 'solid',
width: '0',
shadowColor: 'rgba(0,0,0,0)',
shadowBlur: 5,
shadowOffsetX: 3,
shadowOffsetY: 3,
},
},
}],
// Add series
series: [
{
name: 'Page Views',
type: 'bar',
smooth: true,
symbol: 'none',
symbolSize: 2,
showAllSymbol: true,
barWidth: 10,
itemStyle: {
normal: {
color: 'rgba(63,81,181,1.0)',
borderWidth: 2, borderColor: 'rgba(63,81,181,1)',
areaStyle: { color: 'rgba(63,81,181,1)', type: 'default' }
}
},
data: []
}
]
};
Here is my java-script function from where I want to bind the values dynamically.
// Load data into the ECharts instance
load_graph_with_positions(option);
function load_graph_with_positions(option) {
option.series[0].data[0] = 1234;
myChart.setOption(option);
}
One way to do this is by passing values in an array and then shifting the previous values, while pushing-in the data. Following is the example of shiting and pushing the data:
option.series[0].data.shift();
option.series[0].data.push(json.num);
Hence your function will become:
function load_graph_with_positions(option,values) {
var valuesLength = values.length;
for (var i = 0; i < valuesLength; i++) {
option.series[0].data.shift();
option.series[0].data.push(values[i]);
}
myChart.setOption(option);
}
You can also refer to following github example for dynamic addition:
https://github.com/hisune/Echarts-PHP/blob/master/demo/dynamic.php
I would like to set all colors for the pie slices to gray except for the color pie slice clicked in the legend. I have been only able to figure out how to change the color of only the clicked legend item not the others.
I have tried setting id's to the data points and using e.target but that didn't provide the proper access.
Thanks for your help.
Here is my myFiddle.
$(document).ready(function () {
var myCharts = {
chart: {
renderTo: 'container',
type: 'pie',
backgroundColor: 'rgba(255, 255, 255, 0.1)',
borderColor: 'rgba(255, 255, 255, 0.1)',
margin: [38, 20, 20, 20],
width: 300,
height: 300,
shadow: true,
},
colors: [
'#0066FF',
'#33CC33',
'#FF0000',
'#FFFF00',
],
credits: {
enabled: false
},
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'top',
x: 0,
y: 0
},
title: {
text: 'Net Activations',
verticalAlign: 'bottom',
y: 10
},
subtitle: {
text: '7%',
verticalAlign: 'middle',
y: 30,
style: {
color: 'black',
fontSize: '40px'
}
},
yAxis: {
tickColor: '#FF0000',
tickWidth: 3,
tickInterval: 5
},
xAxis: {
tickColor: '#FF0000',
tickWidth: 3,
tickInterval: 5
},
plotOptions: {
pie: {
states: {
hover: {
enabled: false
}
},
point: {
events: {
legendItemClick: function () {
this.graphic.attr({
fill: '#CCCCCC'
});
return false
}
}
},
dataLabels: {
enabled: true,
distance: 0.1,
color: 'black',
formatter: function () {
return '<b>' + this.point.name + '</b>: ' + this.percentage + ' %';
},
},
innerSize: '60%',
shadow: true,
size: '100%',
allowPointSelect: true,
slicedOffset: 10,
}
},
tooltip: {
enabled: false
},
series: [{
data: [],
showInLegend: true,
}]
};
myCharts.chart.renderTo = 'container';
myCharts.title.text = 'Net Activations';
var actual = 52,
goal = 73 - actual,
ATB = 100 - goal - actual;
myCharts.series[0].data = [{
name: 'Actual',
y: actual,
id: 0
}, {
name: 'goal',
y: goal,
id: 1
}, {
name: 'ATB',
y: ATB,
id: 2
}];
new Highcharts.Chart(myCharts);
});
Instead of attacking the SVG directly with this.graphic.attr, you'd be better off using the API to update the slice. Point.update works well for this:
legendItemClick: function () {
var series = this.series;
for (var i=0; i < series.data.length; i++){
var point = series.data[i];
if (point == this){
// set back to old color
point.update({color: series.chart.options.colors[this.id]});
}else{
// make it gray
point.update({color: '#CCCCCC'});
}
}
return false;
}
Updated fiddle here.
Well, I can get you 50% of the way there:
point: {
events: {
click: function () {
if (event.point.sliced) {
$.each(this.series.data, function (i, e) {
if (!e.sliced) {
this.graphic.attr({
fill: '#CCCCCC'
});
}
});
}
}
}
This still breaks when you re-click the slice to slot it back in - the colors of the other slices are still grey until you click on them. Will need to look more into this.