How can I hide/show a data that in a series? (highchart) - highcharts

I know how to hide a whole series,but I have no idea about how to hide a specific data in a series. here is part of my option:
series: [
{
data: [
{ x: 35, y: 35, z: 50.8, name: "A" ,visible:false},
{ x: 25, y: 75, z: 50.8, name: "B" },
{ x: 45, y: 55, z: 50.8, name: "C", color: "red" }
]
}
mydemo
visible:false is half works , the background is disappeared but the datalabel is still there , I want hide it , and no user interaction.
and I want tigger hide/show on a bubble click like this:
const onClickBubble = event => {
let currentPointName = event.point.name;
console.log(chartRef.current.chart.series[0].options.data);
option.series[0].data.forEach(element => {
if (currentPointName === element.name) {
element.color = "green";
} else {
//hide other bubble here
element.visible = false;
}
});
let NewOptoin = Object.assign({}, option);
setOption(NewOptoin);
};
so this :
events: {
load: function(){
var point = this.series[0].points[0];
['graphic', 'dataLabel'].forEach(function (key) {
if (point[key]) {
point[key].hide();
}
});
}
}
there is no series[x].points in chart option. so this way may not work for me.

You can hide a point in the load event:
chart: {
events: {
load: function(){
var point = this.series[0].points[0];
['graphic', 'dataLabel'].forEach(function (key) {
if (point[key]) {
point[key].hide();
}
});
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/6m4e8x0y/4805/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.SVGElement#hide
https://api.highcharts.com/highcharts/chart.events.load

Related

I want to create map that display USA state, when user click on state it will show that's state's cities. I'm using highchart

I'm using highchart map, that displays the USA state and its counties, but I want to show all cities of the selected state and when someone clicks on the city map it will display pop up model
I want to display all cities of the selected state and when someone clicks on the city map it will display a pop-up model.
The code I'm using right now
<div id="container"></div>
<script>
const drilldown = async function (e) {
// console.log('hover key', e.point.drilldown)
if (!e.seriesOptions) {
const chart = this,
mapKey = `countries/us/${e.point.drilldown}-all`;
// Handle error, the timeout is cleared on success
let fail = setTimeout(() => {
if (!Highcharts.maps[mapKey]) {
chart.showLoading(`<i class="icon-frown"></i> Failed loading ${e.point.name}`);
fail = setTimeout(() => {
chart.hideLoading();
}, 1000);
}
}, 3000);
// Show the Font Awesome spinner
chart.showLoading('<i class="icon-spinner icon-spin icon-3x"></i>');
var topology = await
fetch(https://code.highcharts.com/mapdata/${mapKey}.topo.json)
.then(response => response.json());
// Load the drilldown map
// const topology = await fetch(`https://code.highcharts.com/mapdata/${mapKey}.topo.json`)
// .then(response => response.json());
const data = Highcharts.geojson(topology);
// Set a non-random bogus value
data.forEach((d, i) => {
d.value = i;
console.log('data',d)
});
// Apply the recommended map view if any
chart.mapView.update(
Highcharts.merge(
{ insets: undefined },
topology.objects.default['hc-recommended-mapview']
),
false
);
// Hide loading and add series
chart.hideLoading();
clearTimeout(fail);
chart.addSeriesAsDrilldown(e.point, {
name: e.point.name,
data,
dataLabels: {
enabled: true,
format: '{point.name}'
}
});
}
};
// On drill up, reset to the top-level map view
const drillup = function (e) {
if (e.seriesOptions.custom && e.seriesOptions.custom.mapView) {
e.target.mapView.update(
Highcharts.merge(
{ insets: undefined },
e.seriesOptions.custom.mapView
),
false
);
}
};
(async () => {
const topology = await fetch(
'https://code.highcharts.com/mapdata/countries/us/us-all.topo.json'
).then(response => response.json());
const data = Highcharts.geojson(topology);
const mapView = topology.objects.default['hc-recommended-mapview'];
// Set drilldown pointers
data.forEach((d, i) => {
d.drilldown = d.properties['hc-key'];
d.value = i; // Non-random bogus data
});
// Instantiate the map
Highcharts.mapChart('container', {
chart: {
events: {
drilldown,
drillup,
thrilup
}
},
title: {
text: 'Highcharts Map Drilldown'
},
colorAxis: {
min: 0,
minColor: '#E6E7E8',
maxColor: '#005645'
},
mapView,
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
plotOptions: {
map: {
states: {
hover: {
color: '#EEDD66'
}
}
}
},
series: [{
data,
name: 'USA',
dataLabels: {
enabled: true,
format: '{point.properties.postal-code}'
},
custom: {
mapView
}
}],
drilldown: {
activeDataLabelStyle: {
color: '#FFFFFF',
textDecoration: 'none',
textOutline: '1px #000000'
},
drillUpButton: {
relativeTo: 'spacingBox',
position: {
x: 0,
y: 60
}
}
},
thrilup: {
activeDataLabelStyle: {
color: '#FFFFFF',
textDecoration: 'none',
textOutline: '1px #000000'
},
drillUpButton: {
relativeTo: 'spacingBox',
position: {
x: 0,
y: 60
}
}
}
});
})();

Update xAxis individual label position for printing Highcharts

Is there a way to update specific xAxis label when a user wants to print the chart?
This is the initial chart (inverted column with custom styles). I created xAxis labels with formatter function
xAxis: {
arrowOnEnd: true,
labels: {
x: 40,
formatter: function() {
if (this.isLast) { return 'Less Likely' }
if (this.isFirst) { return 'More Likely' }
}
},
and was able to position them so it looks like inverted xAxis has values from Less likely to More likely as follows
events: {
load: function() {
// https://stackoverflow.com/questions/51656849/xaxis-point-specific-label-positions
const chart = this;
Highcharts.objectEach(chart.xAxis[0].ticks, function(tick: any) {
if (!tick.isNewLabel && tick.isFirst) { tick.label.attr({ y: 25 })}
if (!tick.isNewLabel && tick.isLast) { tick.label.attr({ y: 590 })}
});
},
The problem I have is when I want to print the chart:
xAxis labels gets back to its original location.
I tried to replicate events: { load: ... } logic in beforePrint or wrapping 'print' event to highcharts object, but that doesn't seem to take any effect
beforePrint: function() {
const chart = this;
Highcharts.objectEach(chart.xAxis[0].ticks, function(tick: any) {
if (tick.isFirst) { tick.label.attr({ y: 125 })}
if (tick.isLast) { tick.label.attr({ y: 590 })}
});
}
Highcharts.wrap(Highcharts.Chart.prototype, 'print', function (proceed) {
const chart = this;
Highcharts.objectEach(chart.xAxis[0].ticks, function(tick: any) {
if (tick.isFirst) { tick.label.attr({ y: 25 })}
if (tick.isLast) { tick.label.attr({ y: 590 })}
});
proceed.call(this)
});
I tried tickPositionier but couldn't actually work out how to make that work.
Worth to mention. that afterPrint event with the same logic resets the chart, so I don't understand why one event is working (afterPrint) but the other doesn't (print)
afterPrint: function() {
const chart = this;
Highcharts.objectEach(chart.xAxis[0].ticks, function(tick: any) {
if (tick.isFirst) { tick.label.attr({ y: 25 })}
if (tick.isLast) { tick.label.attr({ y: 590 })}
});
},
Am I missing something here? Why I can't update tick position for printing?
Sidenote - jsfiddle gives me 502 Bad Gateway so I'm unable to demo it there
Changing the load event to render should fix the issue when the chart will be initialized again before the print.
Demo: https://jsfiddle.net/BlackLabel/4qbp1w0z/
chart: {
type: 'bar',
events: {
render: function() {
// https://stackoverflow.com/questions/51656849/xaxis-point-specific-label-positions
const chart = this;
Highcharts.objectEach(chart.xAxis[0].ticks, function(tick) {
if (!tick.isNewLabel && tick.isFirst) {
tick.label.attr({
y: 20
})
}
if (!tick.isNewLabel && tick.isLast) {
tick.label.attr({
y: 350
})
}
});
},
}
},
API: https://api.highcharts.com/highcharts/chart.events.render

How to show the container in a nested treemap?

I have a treemap made of
a big container
with an element
with an element
with an element which is itself made of
an element
an element
another big container
Highcharts.chart('container', {
series: [{
type: "treemap",
animation: false,
data: [
// first big category
{
id: 'B',
name: 'B'
},
{
name: 'Anne',
parent: 'B',
value: 4
}, {
name: 'Peter',
parent: 'B',
value: 1
},
// below is a member of forst big category, but with sub-categories
{
name: 'aaa container',
parent: 'B',
id: 'aaa'
}, {
name: 'Anneinaaa',
parent: 'aaa',
value: 1
}, {
name: 'Rickinaaa',
parent: 'aaa',
value: 3
},
// second big category
{
name: 'Susanne',
parent: 'Kiwi',
value: 2,
color: '#9EDE00'
}
]
}],
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/treemap.js"></script>
<div id="container"></div>
I would like to highlight the fact that there is a container for Rickinaaa and Anneinaaa, with a description.
Right now Rickinaaa and Anneinaaa are at the same level as Anne and Peter, despite the fact that it is their container (the one I do not know how to show) which should be at their level.
An example from ZingCharts which shows this multilayer presentation:
It is much easier to see the box-in-a-box structure.
Is there a way to achieve this in Highcharts? Specifically, how could I have a visible container labelled aaa container which would encompass the rectangles Rickinaaa and Anneinaaa
It can be done by using custom positioning algorithm for treemap. The process is described here: https://www.highcharts.com/docs/chart-and-series-types/treemap (ADD YOUR OWN ALGORITHM section).
I created simplified algorithm for demo purposes (some values are hardcoded):
// Custom positioning algorithm
function myFunction(parent, children) {
childrenAreas = [];
Highcharts.each(children, function(child) {
// Do some calculations
var newLeaf = null;
if (child.id === 'A') {
newLeaf = {
x: 0,
y: 0,
width: 50,
height: 50
};
} else if (child.id === 'B') {
newLeaf = {
x: 50,
y: 0,
width: 50,
height: 50
};
} else if (child.name === 'Rick') {
newLeaf = {
x: parent.x + 10,
y: parent.y + 10,
width: parent.width - 20,
height: (parent.height - 20) / 2
}
} else if (child.name === 'Peter') {
newLeaf = {
x: parent.x + 10,
y: parent.y + 30,
width: parent.width - 20,
height: (parent.height - 20) / 2
}
} else if (child.name === 'Anne') {
newLeaf = {
x: parent.x + 10,
y: 10,
width: parent.width - 20,
height: parent.height - 20
}
}
if (newLeaf) {
childrenAreas.push(newLeaf);
}
});
return childrenAreas;
};
Highcharts.seriesTypes.treemap.prototype.myCustomAlgorithm = myFunction;
By default Highcharts assigns color fill attribute only for the nodes of the Highest level - all other nodes have it set to none. It can be changed manually via CSS:
.highcharts-internal-node {
fill: #bada55
}
I also did a small change in the core code so that parent levels are drawn underneath the child ones:
(function(H) {
var grep = H.grep,
each = H.each,
seriesTypes = H.seriesTypes;
H.seriesTypes.treemap.prototype.drawPoints = function() {
var series = this,
points = grep(series.points, function(n) {
return n.node.visible;
});
each(points, function(point) {
var groupKey = 'level-group-' + point.node.levelDynamic;
if (!series[groupKey]) {
series[groupKey] = series.chart.renderer.g(groupKey)
.attr({
// CHANGED FROM: zIndex: 1000 - point.node.levelDynamic
zIndex: 1000 + point.node.levelDynamic // #todo Set the zIndex based upon the number of levels, instead of using 1000
})
.add(series.group);
}
point.group = series[groupKey];
});
// Call standard drawPoints
seriesTypes.column.prototype.drawPoints.call(this);
// If drillToNode is allowed, set a point cursor on clickables & add drillId to point
if (series.options.allowDrillToNode) {
each(points, function(point) {
if (point.graphic) {
point.drillId = series.options.interactByLeaf ? series.drillToByLeaf(point) : series.drillToByGroup(point);
}
});
}
}
})(Highcharts);
Live demo: https://jsfiddle.net/BlackLabel/wfed4jeo/

Can I assign a different radius when click a pie slice using Highcharts?

I am using Highcharts it is working fine but i want to change in pie slice when i click on single pie slice then that slice overlap two slice(right or left slice).
Below is the image attached tha i have done in pie chart.
Below is the image attached of the expexted pie chart result
You can add your own method, which will resize shape on click, for example: http://jsfiddle.net/BlackLabel/8vd6cod1/
function resizeSlice(point, change) {
// Original shape params are stored in shapeArgs:
var shape = point.shapeArgs;
if (point.graphic) {
point.graphic.attr({
// "r" is outer radius:
r: shape.r + change,
// "innerR" is inner radius:
innerR: shape.innerR - change
});
}
}
// Build the chart
Highcharts.chart('container', {
chart: {
type: 'pie',
events: {
// On window resize, apply change:
redraw: function() {
Highcharts.each(this.series[0].points, function(point) {
resizeSlice(point, point.customResized ? 5 : 0)
});
}
}
},
plotOptions: {
pie: {
innerSize: '90%',
cursor: 'pointer',
dataLabels: {
enabled: false
},
point: {
events: {
click: function() {
var change = 0;
// Custom param, can be called whatever we want:
this.customResized = !this.customResized;
if (this.customResized) {
// Let's resize!
change = 5;
}
resizeSlice(this, change);
}
}
}
}
},
series: [{
data: [3, 4, 5, 6]
}]
});
I have make some change to this code for re size all other pie.
: http://jsfiddle.net/8vd6cod1/2/
function resizeSlice(point, change) {
// Original shape params are stored in shapeArgs:
var shape = point.shapeArgs;
if (point.graphic) {
point.graphic.attr({
// "r" is outer radius:
r: shape.r + change,
// "innerR" is inner radius:
innerR: shape.innerR - change
});
}
}
// Build the chart
Highcharts.chart('container', {
chart: {
type: 'pie',
events: {
// On window resize, apply change:
redraw: function() {
Highcharts.each(this.series[0].points, function(point) {
resizeSlice(point, point.customResized ? 5 : 0)
});
}
}
},
plotOptions: {
pie: {
innerSize: '90%',
cursor: 'pointer',
dataLabels: {
enabled: false
},
point: {
events: {
click: function() {
Highcharts.each(this.series.points, function(point) {
resizeSlice(point, 0)
});
var change = 0;
// Custom param, can be called whatever we want:
this.customResized = !this.customResized;
if (this.customResized) {
// Let's resize!
change = 5;
}
resizeSlice(this, change);
}
}
}
}
},
series: [{
data: [3, 4, 5, 6]
}]
});

Highcharts pie graph with two rings filtering

I have a pie chart here that I'm working on that has two "rings" in it. The inner ring is just a summation of the outer ring for that given category.
Here is the fiddle: http://jsfiddle.net/jeffvan576/a50859s7/1/
(Apologies for the code - it's a bit of a mess right now)
I've been messing around with the showInLegend functionality but that will (as it's intended) only pull out the given piece of the pie chart. So, for instance, if you click google, it pulls out that piece of the pie chart but leaves the outer ring. To completely eliminate google you need to click "google", "match", "funds added" and "organic" for google.
My question is, is there a way to remove the entire slice (google and all it's children) from the chart at once?
The issue is that in order to get the functionality / layout on the chart that I need, this pie chart is actually built out of two series.
ShowInLegend code:
pie: {
shadow: false,
center: ['50%', '50%'],
showInLegend: true
}
I started building a custom visibility function at the bottom of the fiddle but dialed it back until I understood showInLegend a little better.
Thanks in advance!
you can achieve this by getting name of series on which clicked by using http://api.highcharts.com/highcharts#plotOptions.pie.events.click of plotoptions -> pie.
after that calling visibility function to hide Channel series along with its children to hide/show.
Event:
plotOptions: {
pie: {
shadow: false,
center: ['50%', '50%'],
showInLegend: true,
point: {
events: {
}
}
}
}
also static line put into visibility function to hide/show need to remove.
// chart.series[0].data[0].visible = false;
http://jsfiddle.net/a50859s7/27/
Full code:
$(function () {
var dataObject = {
facebook: {
'organic': 10.85,
'match': 7.35,
'fundsadded': 33.06,
'total': 0,
'status': 'disabled'
},
google: {
'organic': 10.85,
'match': 7.35,
'fundsadded': 33.06,
'total': 0,
'status': 'disabled'
},
email: {
'organic': 10.85,
'match': 7.35,
'fundsadded': 33.06,
'total': 0,
'status': 'enabled'
},
colorSelections: {
'facebook': '#3b5998',
'google': '#dd4b39',
'disabled': '#c6c6c6'
}
}
var sumObjects = function () {
for (var channel in dataObject) {
if (channel === 'colorSelections') continue;
var sum = 0;
for (var key in dataObject[channel]) {
if (key === 'status') continue;
sum += dataObject[channel][key];
}
dataObject[channel].total = sum;
}
}
sumObjects();
var colors = Highcharts.getOptions().colors,
categories = ['Facebook', 'Google', 'Email'],
data = [{
y: dataObject.facebook.total + 1,
//color: dataObject.facebook.status === 'disabled' ? dataObject.colorSelections.disabled : dataObject.colorSelections.facebook,
color: 'rgba(59, 89, 152, 0.3)',
drilldown: {
name: 'Facebook',
categories: ['organic', 'match', 'funds added'],
data: [
dataObject.facebook.organic,
dataObject.facebook.match,
dataObject.facebook.fundsadded],
color: 'rgba(59, 89, 152, 0.3)'
},
}, {
y: dataObject.google.total + 1,
color: '#dd4b39',
drilldown: {
name: 'Google',
categories: ['organic', 'match', 'funds added'],
data: [
dataObject.google.organic,
dataObject.google.match,
dataObject.google.fundsadded],
color: '#e46f61'
}
}, {
y: dataObject.email.total + 1,
color: colors[2],
drilldown: {
name: 'Email',
categories: ['organic', 'match', 'funds added'],
data: [
dataObject.email.organic,
dataObject.email.match,
dataObject.email.fundsadded],
color: colors[2]
}
}],
browserData = [],
versionsData = [],
i,
j,
dataLen = data.length,
drillDataLen,
brightness;
// Build the data arrays
for (i = 0; i < dataLen; i += 1) {
// add browser data
browserData.push({
name: categories[i],
y: data[i].y,
color: data[i].color
});
// add version data
drillDataLen = data[i].drilldown.data.length;
for (j = 0; j < drillDataLen; j += 1) {
brightness = 0.2 - (j / drillDataLen) / 5;
versionsData.push({
name: data[i].drilldown.categories[j],
y: ((data[i].drilldown.data[j] / browserData[0].y) * 100),
color: Highcharts.Color(data[i].color).brighten(brightness).get()
});
}
}
// Create the chart
$('#container').highcharts({
chart: {
type: 'pie'
},
title: {
text: 'Browser market share, April, 2011'
},
yAxis: {
title: {
text: 'Total percent market share'
}
},
plotOptions: {
pie: {
shadow: false,
center: ['50%', '50%'],
showInLegend: true,
point: {
events: {
click: function (event) {
var seriesIndex;
var secondarySeriesIndex;
if (this.name == 'Facebook') {
seriesIndex = 0;
secondarySeriesIndex = 0;
} else if (this.name == 'Google') {
seriesIndex = 1;
secondarySeriesIndex = 3;
} else if (this.name == 'Email') {
seriesIndex = 2;
secondarySeriesIndex = 6;
}
var chart = $('#container').highcharts();
visibility(chart.series[0].data[seriesIndex]);
visibility(chart.series[1].data[secondarySeriesIndex]);
visibility(chart.series[1].data[secondarySeriesIndex + 1]);
visibility(chart.series[1].data[secondarySeriesIndex + 2]);
}
}
}
}
},
tooltip: {
valueSuffix: '%'
},
series: [{
name: 'Channel',
type: 'pie',
data: browserData,
size: '120%',
dataLabels: {
formatter: function () {
return this.y > 5 ? this.point.name : null;
},
color: 'white',
distance: -30
}
}, {
name: 'Added',
type: 'pie',
data: versionsData,
size: '120%',
innerSize: '80%',
dataLabels: {
formatter: function () {
// display only if larger than 1
return this.y > 1 ? '<b>' + this.point.name + ':</b> ' + this.y + '%' : null;
}
}
}]
});
var visibility = function (series) {
series.visible ? series.graphic.hide() : series.graphic.show();
// chart.series[0].data[0].visible = false;
}
var chart = $('#container').highcharts();
$('.update').click(function () {
visibility(chart.series[0].data[0]);
visibility(chart.series[1].data[0]);
visibility(chart.series[1].data[1]);
visibility(chart.series[1].data[2]);
chart.redraw();
});
function synchronizePieSeries(event, slice) {
debugger;
$(chart.series[1].data).each(function (i, e) {
if (slice.name === e.name) {
slice.visible ? e.graphic.hide() : e.graphic.show();
}
});
}
//$('.update').click(function (event) {
// synchronizePieSeries(event, this);
//});
});

Resources