How to show relation between two boxes containing same data in two different treemaps - highcharts

I am using treemaps for a comparison purpose. I am using highchart.com for visualization.
I am showing two different treemaps side by side and hence providing a way of comparison for users. I want to link two same boxes in different treemaps. For example, I have two different treemaps and both have word "Bananas" in common. I want that when I hover on Box containing "Bananas" in first treemap, it highlights the same box of "Bananas" in 2nd treemap.
Is this even possible?
here is the code which generates the treemap.
Highcharts.chart('treemap1', {
series: [{
type: "treemap",
layoutAlgorithm: 'stripes',
alternateStartingDirection: true,
levels: [{
level: 1,
layoutAlgorithm: 'sliceAndDice',
dataLabels: {
enabled: true,
align: 'left',
verticalAlign: 'top',
style: {
fontSize: '15px',
fontWeight: 'bold'
}
}
}],
data: [{
id: 'A',
name: 'Apples',
color: "#EC2500"
}, {
id: 'B',
name: 'Bananas',
color: "#ECE100"
}, {
id: 'O',
name: 'Oranges',
color: '#EC9800'
}, {
name: 'Anne',
parent: 'A',
value: 5
}, {
name: 'Rick',
parent: 'A',
value: 3
}, {
name: 'Peter',
parent: 'A',
value: 4
}, {
name: 'Anne',
parent: 'B',
value: 4
}, {
name: 'Rick',
parent: 'B',
value: 10
}, {
name: 'Peter',
parent: 'B',
value: 1
}, {
name: 'Anne',
parent: 'O',
value: 1
}, {
name: 'Rick',
parent: 'O',
value: 3
}, {
name: 'Peter',
parent: 'O',
value: 3
}, {
name: 'Susanne',
parent: 'Kiwi',
value: 2,
color: '#9EDE00'
}]
}],
title: {
text: 'Treemap 1'
}
});
Highcharts.chart('treemap2', {
series: [{
type: "treemap",
layoutAlgorithm: 'stripes',
alternateStartingDirection: true,
levels: [{
level: 1,
layoutAlgorithm: 'sliceAndDice',
dataLabels: {
enabled: true,
align: 'left',
verticalAlign: 'top',
style: {
fontSize: '15px',
fontWeight: 'bold'
}
}
}],
data: [{
id: 'A',
name: 'Apples',
color: "#EC2500"
}, {
id: 'B',
name: 'Bananas',
color: "#ECE100"
}, {
id: 'O',
name: 'Oranges',
color: '#EC9800'
}, {
name: 'Anne',
parent: 'A',
value: 5
}, {
name: 'Rick',
parent: 'A',
value: 3
}, {
name: 'Peter',
parent: 'A',
value: 4
}, {
name: 'Anne',
parent: 'B',
value: 4
}, {
name: 'Rick',
parent: 'B',
value: 10
}, {
name: 'Peter',
parent: 'B',
value: 1
}, {
name: 'Anne',
parent: 'O',
value: 1
}, {
name: 'Rick',
parent: 'O',
value: 3
}, {
name: 'Peter',
parent: 'O',
value: 3
}, {
name: 'Susanne',
parent: 'Kiwi',
value: 2,
color: '#9EDE00'
}]
}],
title: {
text: 'Treemap 2'
}
});
.treemap-chart {
float: left;
width: 50%
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/treemap.js"></script>
<div id="treemap1" class="treemap-chart"></div>
<div id="treemap2" class="treemap-chart"></div>
Image of the output here:
codeoutput

You can do this by setting the state of a the hovered point in the mouseOver event and removing the state in the mouseOut event. Like this for the first chart, and the same for second chart changing the variable chart2 to chart1:
plotOptions: {
series: {
point: {
events: {
mouseOver: function(event) {
for (var i = 0; i < chart2.series[0].data.length; i++) {
if (chart2.series[0].data[i].name == event.target.name && chart2.series[0].data[i].parent == event.target.parent) {
chart2.series[0].data[i].setState('hover')
}
}
},
mouseOut: function(event) {
for (var i = 0; i < chart2.series[0].data.length; i++) {
if (chart2.series[0].data[i].name == event.target.name && chart2.series[0].data[i].parent == event.target.parent) {
chart2.series[0].data[i].setState('')
}
}
}
}
}
}
},
var chart1 = Highcharts.chart('treemap1', {
plotOptions: {
series: {
point: {
events: {
mouseOver: function(event) {
for (var i = 0; i < chart2.series[0].data.length; i++) {
if (chart2.series[0].data[i].name == event.target.name && chart2.series[0].data[i].parent == event.target.parent) {
chart2.series[0].data[i].setState('hover')
}
}
},
mouseOut: function(event) {
for (var i = 0; i < chart2.series[0].data.length; i++) {
if (chart2.series[0].data[i].name == event.target.name && chart2.series[0].data[i].parent == event.target.parent) {
chart2.series[0].data[i].setState('')
}
}
}
}
}
}
},
series: [{
type: "treemap",
layoutAlgorithm: 'stripes',
alternateStartingDirection: true,
levels: [{
level: 1,
layoutAlgorithm: 'sliceAndDice',
dataLabels: {
enabled: true,
align: 'left',
verticalAlign: 'top',
style: {
fontSize: '15px',
fontWeight: 'bold'
}
}
}],
data: [{
id: 'A',
name: 'Apples',
color: "#EC2500"
}, {
id: 'B',
name: 'Bananas',
color: "#ECE100"
}, {
id: 'O',
name: 'Oranges',
color: '#EC9800'
}, {
name: 'Anne',
parent: 'A',
value: 5
}, {
name: 'Rick',
parent: 'A',
value: 3
}, {
name: 'Peter',
parent: 'A',
value: 4
}, {
name: 'Anne',
parent: 'B',
value: 4
}, {
name: 'Rick',
parent: 'B',
value: 10
}, {
name: 'Peter',
parent: 'B',
value: 1
}, {
name: 'Anne',
parent: 'O',
value: 1
}, {
name: 'Rick',
parent: 'O',
value: 3
}, {
name: 'Peter',
parent: 'O',
value: 3
}, {
name: 'Susanne',
parent: 'Kiwi',
value: 2,
color: '#9EDE00'
}]
}],
title: {
text: 'Treemap 1'
}
});
var chart2 = Highcharts.chart('treemap2', {
plotOptions: {
series: {
point: {
events: {
mouseOver: function(event) {
for (var i = 0; i < chart1.series[0].data.length; i++) {
if (chart1.series[0].data[i].name == event.target.name && chart1.series[0].data[i].parent == event.target.parent) {
chart1.series[0].data[i].setState('hover')
}
}
},
mouseOut: function(event) {
for (var i = 0; i < chart1.series[0].data.length; i++) {
if (chart1.series[0].data[i].name == event.target.name && chart1.series[0].data[i].parent == event.target.parent) {
chart1.series[0].data[i].setState('')
}
}
}
}
}
}
},
series: [{
type: "treemap",
layoutAlgorithm: 'stripes',
alternateStartingDirection: true,
levels: [{
level: 1,
layoutAlgorithm: 'sliceAndDice',
dataLabels: {
enabled: true,
align: 'left',
verticalAlign: 'top',
style: {
fontSize: '15px',
fontWeight: 'bold'
}
}
}],
data: [{
id: 'A',
name: 'Apples',
color: "#EC2500"
}, {
id: 'B',
name: 'Bananas',
color: "#ECE100"
}, {
id: 'O',
name: 'Oranges',
color: '#EC9800'
}, {
name: 'Anne',
parent: 'A',
value: 5
}, {
name: 'Rick',
parent: 'A',
value: 3
}, {
name: 'Peter',
parent: 'A',
value: 4
}, {
name: 'Anne',
parent: 'B',
value: 4
}, {
name: 'Rick',
parent: 'B',
value: 10
}, {
name: 'Peter',
parent: 'B',
value: 1
}, {
name: 'Anne',
parent: 'O',
value: 1
}, {
name: 'Rick',
parent: 'O',
value: 3
}, {
name: 'Peter',
parent: 'O',
value: 3
}, {
name: 'Susanne',
parent: 'Kiwi',
value: 2,
color: '#9EDE00'
}]
}],
title: {
text: 'Treemap 2'
}
});
.treemap-chart {
float: left;
width: 50%
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/treemap.js"></script>
<div id="treemap1" class="treemap-chart"></div>
<div id="treemap2" class="treemap-chart"></div>
Working jsfiddle example: https://jsfiddle.net/ewolden/czn1rjxu/2/

Related

HighCharts - Single legend for two columns in a Stack Column chart

I have four stack in a Stacked Column chart: "One Completed", "One Pending", "Two Completed", "Two Pending".
By default, I have four legends for these stacks.
What I want is to have two legends: "One" and "Two". Is it possible using Highcharts?
Edit:
Added code. Some of text/logic are removed. Most of the styling is what I found on Internet somewhere.
Highcharts.chart('', {
chart: {
type: 'column',
},
title: {
text: '',
},
xAxis: {
categories: c,
labels: {
y: 40
}
},
yAxis: {
min: 0,
title: {
text: ''
},
stackLabels: {
enabled: true,
verticalAlign: 'bottom',
crop: false,
overflow: 'none',
y: 20,
formatter: function () {
return this.stack
},
style: {
fontSize: '9px',
color: (
Highcharts.defaultOptions.title.style &&
Highcharts.defaultOptions.title.style.color
) || 'gray'
}
}
},
credits: {
enabled: false
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: Highcharts.defaultOptions.legend.backgroundColor || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
formatter: function () {
//custom logic
}
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true
}
},
series: {
cursor: 'pointer',
events: {
click: function (event) {
//custom click to filter logic
}
}
}
},
series: [{
name: 'One Pending',
data: one_series_pending,
color: '#7cb5ec',
stack: 'Pending'
}, {
name: 'One Completed',
data: one_series_completed,
color: '#7cb5ec',
stack: 'Completed'
}, {
name: 'Two Pending',
data: two_series_pending,
color: '#434348',
stack: 'Pending'
}, {
name: 'Two Completed',
data: two_series_completed,
color: '#434348',
stack: 'Completed'
}]
});
Sample chart:
I want single legend for same color(two stacks)
You can link one series with another and have one legend item for them by using linkedTo property.
series: [{
name: 'One Pending',
data: [9, 5],
color: '#7cb5ec',
stack: 'Pending'
}, {
name: 'One Completed',
data: [6, 2],
color: '#7cb5ec',
stack: 'Completed',
linkedTo: 0
}, {
name: 'Two Pending',
data: [35, 5],
color: '#434348',
stack: 'Pending'
}, {
name: 'Two Completed',
data: [3, 0],
color: '#434348',
stack: 'Completed',
linkedTo: 2
}]
Live demo: http://jsfiddle.net/BlackLabel/eh5m10q9/
API Reference: https://api.highcharts.com/highcharts/series.column.linkedTo

Highcharts treemap data labels overflow

while using Highcharts multi level treemap I ran into data labels overflow issue. Data labels overflows to other area. This works fine at level 1 & 2 when I use option overflow: 'crop' but does not work at level 3. Any idea where it is going wrong.
Here in example area with name:F data label overflows but data label with name:C at level 2 does not overflow.
Here is fiddle example.
$(function() {
var H = Highcharts;
$('#container').highcharts({
chart: {
type: 'treemap',
width: 500
},
title: {
text: null
},
plotOptions: {
series: {
layoutAlgorithm: 'stripes',
alternateStartingDirection: true,
levels: [{
level: 1,
dataLabels: {
enabled: true,
align: 'left',
verticalAlign: 'top'
}
}, {
level: 2,
dataLabels: {
formatter: function () {
return this.point.realValue;
},
overflow: 'crop'
}
}, {
level: 3,
dataLabels: {
formatter: function () {
return this.point.realValue;
},
overflow: 'crop'
}
}]
}
},
series: [{
data: [{
name: 'A',
id: 'A',
value: 1,
color: '#FFFFFF'
}, {
name: 'B',
id: 'B',
value: 1,
color: '#FFFFFF'
}, {
name: 'C',
parent: 'A',
id: 'A-1',
value: 10,
realValue: 'thisisveryveryveryveryveryverylongteststring',
color: '#ECEA8E'
}, {
name: 'D',
parent: 'A',
id: 'A-2',
color: '#FFFFFF'
}, {
name: 'E',
parent: 'A-2',
id: 'A-2-1',
value: 10,
realValue: 'A',
color: '#599753'
}, {
name: 'F',
parent: 'A-2',
id: 'A-2-2',
value: 10,
realValue: 'thisisveryveryveryverylongteststring',
color: '#1B3C40'
}, {
name: 'G',
parent: 'B',
id: 'B-1',
value: 10,
realValue: 'A',
color: '#ECEA8E'
}, {
name: 'H',
parent: 'B',
id: 'B-2',
color: '#FFFFFF'
}, {
name: 'I',
parent: 'B-2',
id: 'B-2-1',
value: 10,
realValue: 'A',
color: '#599753'
}, {
name: 'J',
parent: 'B-2',
id: 'B-2-2',
value: 10,
realValue: 'A',
color: '#1B3C40'
}]
}]
});
});
Unfortunately, Highcharts doesn't hide labels when they don't fit treemap point area. As a workaround, you can loop through each data point and check if label related to it is wider. If it is wider just hide it.
Code:
chart: {
type: 'treemap',
width: 500,
events: {
load: function() {
var chart = this,
series = chart.series[0],
pointWidth,
labelWidth;
series.data.forEach(function(point) {
if (point.dataLabel) {
pointWidth = point.shapeArgs.width;
labelWidth = point.dataLabel.width;
if (labelWidth > pointWidth) {
point.dataLabel.hide();
}
}
});
}
}
}
Demo:
https://jsfiddle.net/BlackLabel/h65xm4qb/
API reference:
https://api.highcharts.com/class-reference/Highcharts.SVGElement#hide

Treemap with Multiple Series

I am trying to create TreeMap with multiple series, the series are getting plotted on the graph with both series clubbed together, but I want only one series to be displayed at a time. Basically legand can be used but for treemap it's showing values.
This is the jsfiddle I am trying to work on
JavaScript files used
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/heatmap.js"></script>
<script src="https://code.highcharts.com/modules/treemap.js"></script>
<div id="container"></div>
The treemap should be updated as per the series selected.
Highchart Bound Using
Highcharts.chart('container', {
colorAxis: {
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0]
},
legend: {
enabled: true,
},
series: [{
name:"Series 1",
stack: 'aeroplanes',
type: 'treemap',
layoutAlgorithm: 'squarified',
data: [{
name: 'A -Series 1',
value: 6,
colorValue: 1
}, {
name: 'B -Series 1',
value: 6,
colorValue: 2
}, {
name: 'C -Series 1',
value: 4,
colorValue: 3
}, {
name: 'D -Series 1',
value: 3,
colorValue: 4
}, {
name: 'E -Series 1',
value: 2,
colorValue: 5
}, {
name: 'F -Series 1',
value: 2,
colorValue: 6
}, {
name: 'G -Series 1',
value: 1,
colorValue: 7
}]
},
// Second Series
{
name:"Series 2",
type: 'treemap',
stack: 'aeroplanes2',
layoutAlgorithm: 'squarified',
visible:true,
data: [{
name: 'AA -Series 2',
value: 16,
colorValue: 2
}, {
name: 'BB -Series 2',
value: 26,
colorValue: 2
}, {
name: 'Cc -Series 2',
value: 14,
colorValue: 2
}, {
name: 'Dd -Series 2',
value: 13,
colorValue: 2
}, {
name: 'Ee -Series 2',
value: 12,
colorValue: 2
}, {
name: 'Ff -Series 2',
value: 12,
colorValue: 2
}, {
name: 'Gg -Series 2',
value: 11,
colorValue: 2
}]
}],
title: {
text: 'Highcharts Treemap'
},
plotOptions: {
treemap: {
stacking: 'percent'
}
},
});
By default showInLegend equals to false for treemap series - it needs to be enabled manually. In legendItemClick event I handled series visibility toggling:
plotOptions: {
treemap: {
showInLegend: true,
events: {
legendItemClick: function() {
this.chart.series.forEach((s) => s.setVisible());
return false;
}
}
}
}
Live demo: http://jsfiddle.net/kkulig/0n49vv74/
API references:
https://api.highcharts.com/highcharts/plotOptions.treemap.events.legendItemClick
https://api.highcharts.com/highcharts/plotOptions.treemap.showInLegend
https://api.highcharts.com/class-reference/Highcharts.Series#setVisible

Highcharts - Tree map rectangles are showing the next level

I am using Highcharts Treemap and I want to prevent from showing the next level in every level of the treemap.
I want that every object on the treemap will be with only one color.
Here is my code:
Highcharts.chart('myChart', {
tooltip: {
backgroundColor: 'black',
style: {
"color": "white",
"font": "Roboto"
},
borderColor: 'black',
borderRadius: 5,
},
colorAxis: {
minColor: '#ffcfab',
maxColor: '#ff5e43' //'#FF5E43',
},
legend: {
enabled: false
},
series: [{
type: 'treemap',
layoutAlgorithm: 'squarified',
allowDrillToNode: true,
animationLimit: 1000,
dataLabels: {
enabled: false
},
levelIsConstant: false,
levels: [{
level: 1,
dataLabels: {
enabled: true
},
borderWidth: 3
}],
data: result
}],
title: {
text: 'All Data Sources',
margin: 1,
style: {
font: 'Roboto Condensed,sans-serif',
fontSize: '24px',
fontFamily: 'Roboto Condensed',
fontWeight: 700,
display: 'block',
}
}
})
Thanks In Advance.
Setting opacity to 0 for the series seems to be fixing your problem.
Demo: http://jsfiddle.net/qa2czu8y/
$(function() {
Highcharts.chart('container', {
title: {
text: 'All Data Sources',
margin: 1,
style: {
font: 'Roboto Condensed,sans-serif',
fontSize: '24px',
fontFamily: 'Roboto Condensed',
fontWeight: 700,
display: 'block',
}
},
series: [{
type: 'treemap',
layoutAlgorithm: 'squarified',
allowDrillToNode: true,
animationLimit: 1000,
dataLabels: {
enabled: false
},
levelIsConstant: false,
levels: [{
level: 1,
dataLabels: {
enabled: true
},
borderWidth: 3,
}],
opacity: 0,
data: [{
id: 'A',
name: 'Apples'
}, {
id: 'B',
name: 'Bananas'
}, {
id: 'O',
name: 'Oranges'
}, {
name: 'Anne',
parent: 'A',
value: 5,
colorValue: 5
}, {
name: 'Rick',
parent: 'A',
value: 3,
colorValue: 3
}, {
name: 'Peter',
parent: 'A',
value: 4,
colorValue: 4
}, {
name: 'Anne',
parent: 'B',
value: 4,
colorValue: 4
}, {
name: 'Rick',
parent: 'B',
value: 10,
colorValue: 10
}, {
name: 'Peter',
parent: 'B',
value: 1,
colorValue: 1
}, {
name: 'Anne',
parent: 'O',
value: 1,
colorValue: 1
}, {
name: 'Rick',
parent: 'O',
value: 3,
colorValue: 3
}, {
name: 'Peter',
parent: 'O',
value: 3,
colorValue: 3
}, {
name: 'Susanne',
parent: 'Kiwi',
value: 2,
colorValue: 2
}]
}],
tooltip: {
backgroundColor: 'black',
style: {
"color": "white",
"font": "Roboto"
},
borderColor: 'black',
borderRadius: 5
},
colorAxis: {
minColor: '#ffcfab',
maxColor: '#ff5e43' //'#FF5E43',
},
legend: {
enabled: false
},
});
});
#container {
min-width: 300px;
max-width: 600px;
margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/heatmap.js"></script>
<script src="https://code.highcharts.com/modules/treemap.js"></script>
<div id="container"></div>

how to create a responsive custom label in highchart

I create a scatter chart and will add a label on a box that has been specified, I've managed to make his label, but when her screen minimized, do not adjust the position of its labels.
labels: {
items : [
{
html : 'Prioritas 4',
style : {
left : '380%',
top : '60px',
fontSize : '10px'
}
},
{
html : 'Prioritas 3',
style : {
left : '660%',
top : '60px',
fontSize : '10px'
}
}
]
},
and my complete code is
$('#ketenagalistrikan-pembenahan-layanan-chart').highcharts({
chart: {
type: 'scatter',
zoomType: 'xy'
},
title: {
text: 'Pembenahan Dimensi Layanan'
},
subtitle: {
text: 'Source: rad-research.com'
},
labels: {
items : [
{
html : 'Prioritas 4',
style : {
left : '380%',
top : '60px',
fontSize : '10px'
}
},
{
html : 'Prioritas 3',
style : {
left : '660%',
top : '60px',
fontSize : '10px'
}
}
]
},
xAxis: {
title: {
enabled: true,
text: 'Kepentingan'
},
min: -0.5,
max: 39.3,
startOnTick: true,
endOnTick: true,
showLastLabel: true,
plotLines: [{
color: 'black',
dashStyle: 'dot',
width: 2,
value: 12.7,
zIndex: 3
},{
color: 'black',
dashStyle: 'dot',
width: 2,
value: 26,
zIndex: 3
},{
color: 'black',
dashStyle: 'dot',
width: 2,
value: 39.3,
zIndex: 3
}]
},
yAxis: {
title: {
text: 'Kepuasan'
},
tickInterval: 8.9,
startOnTick: true,
endOnTick: true,
showLastLabel: true,
plotLines: [{
color: 'black',
dashStyle: 'dot',
width: 2,
value: 46.2,
zIndex: 3
},{
color: 'black',
dashStyle: 'dot',
width: 2,
value: 55.2,
zIndex: 3
}]
},
plotOptions: {
scatter: {
marker: {
radius: 5,
states: {
hover: {
enabled: true,
lineColor: 'rgb(100,100,100)'
}
}
},
states: {
hover: {
marker: {
enabled: false
}
}
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '{point.x} cm, {point.y} kg'
}
}
},
series: [{
name: 'Marketing',
data: [[8.75, 45.8]]
},{
name: 'Sales',
data: [[15.0, 43.6]]
},{
name: 'Aktivasi/Instalasi',
data: [[-0.3, 53.2]]
},{
name: 'Contact Center',
data: [[1, 52.2]]
},{
name: 'Customer Account',
data: [[-0.3, 60.1]]
},{
name: 'Field Support',
data: [[30.5, 40.3]]
},{
name: 'Billing',
data: [[37.5, 59.2]]
}]
});
Labels in this case are static, so unless you manually redraw them they will will not be responsive.
I prefer another way - you can use renderer and have control rendered objects completely. With the help axis.toPixels() method you can easily make them responsive and stays in the fixed value.
Create item on load event:
load: function () {
this.customTexts = [];
var text = this.renderer.text(
'Responsive text',
this.xAxis[0].toPixels(15),
this.yAxis[0].toPixels(50)
)
.css({
fontSize: '10px'
})
.add();
this.customTexts.push(text);
},
Redraw the item on redraw event:
redraw: function () {
this.customTexts[0].attr({
x: this.xAxis[0].toPixels(15),
y: this.yAxis[0].toPixels(50)
});
}
Example: http://jsfiddle.net/hfev4w7c/

Resources