AmCharts - show tooltip for all categories in stacked bar chart - tooltip

I'm working on a stacked bar chart and want to display the tooltip for all categories at the same time when hovering one of them.
For instance, in this amCharts demo code I want to show the tooltip for marketing (purple) for all countries when hovering one country.
// Apply chart themes
am4core.useTheme(am4themes_animated);
am4core.useTheme(am4themes_kelly);
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.marginRight = 400;
// Add data
chart.data = [{
"country": "Lithuania",
"research": 501.9,
"marketing": 250,
"sales": 199
}, {
"country": "Czech Republic",
"research": 301.9,
"marketing": 222,
"sales": 251
}, {
"country": "Ireland",
"research": 201.1,
"marketing": 170,
"sales": 199
}, {
"country": "Germany",
"research": 165.8,
"marketing": 122,
"sales": 90
}, {
"country": "Australia",
"research": 139.9,
"marketing": 99,
"sales": 252
}, {
"country": "Austria",
"research": 128.3,
"marketing": 85,
"sales": 84
}, {
"country": "UK",
"research": 99,
"marketing": 93,
"sales": 142
}, {
"country": "Belgium",
"research": 60,
"marketing": 50,
"sales": 55
}, {
"country": "The Netherlands",
"research": 50,
"marketing": 42,
"sales": 25
}];
//console.log('chart', chart);
// Create axes
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "country";
categoryAxis.title.text = "Local country offices";
categoryAxis.renderer.grid.template.location = 0;
categoryAxis.renderer.minGridDistance = 20;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.title.text = "Expenditure (M)";
// Create series
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.valueY = "research";
series.dataFields.categoryX = "country";
series.name = "Research";
series.tooltipText = "{name}: [bold]{valueY}[/]";
series.stacked = true;
var series2 = chart.series.push(new am4charts.ColumnSeries());
series2.dataFields.valueY = "marketing";
series2.dataFields.categoryX = "country";
series2.name = "Marketing";
series2.tooltipText = "{name}: [bold]{valueY}[/]";
series2.stacked = true;
var series3 = chart.series.push(new am4charts.ColumnSeries());
series3.dataFields.valueY = "sales";
series3.dataFields.categoryX = "country";
series3.name = "Sales";
series3.tooltipText = "{name}: [bold]{valueY}[/]";
series3.stacked = true;
// Add cursor
chart.cursor = new am4charts.XYCursor();
https://codepen.io/team/amcharts/pen/GdQWxz
I tried using a cursor but that only shows all tooltips for the specific category. I tried to add an event handler without any luck.
Anyone have a suggestion if it's do-able.

Related

Highmaps mix Bubble map and maplines causes map offset

I'm working on a Highchart map mixing Bubble map an mapline.
I use a first serie to show the map and color region depending on a measure range and a second serie to display a bubble on a region
var data = [
["05", 48810.00, 48810, 10, 19768, -1],
["09", 39239.00, 39239, 10, 13348, -1],
["10", 14974.00, 14974, 10, 7252, -1],
["11", 57124.00, 57124, 10, 26272, -1],
["14", 38821.00, 38821, 10, 17547, -1]
], maxSize = 0;
var all_codes = ["05", "09", "10", "11", "14"];
var Color = [];
Color[0] = "rgba(116, 171, 226, 0.8)";
Color[1] = "rgba(239, 141, 93, 0.8)";
Color[2] = "rgba(63, 182, 142, 0.8)";
Color[3] = "rgba(240, 106, 147, 0.8)";
Color[4] = "rgba(169, 125, 216, 0.8)";
Color[5] = "rgba(58, 181, 194, 0.8)";
Color[6] = "rgba(105, 115, 246, 0.8)";
Color[7] = "rgba(205, 89, 177, 0.8)";
Color[8] = "rgba(140, 162, 171, 0.8)";
Color[9] = "rgba(243, 135, 135, 0.8)";
Color[10] = "rgba(77, 120, 162, 0.8)";
Color[11] = "rgba(24, 102, 180, 0.8)";
Color[12] = "rgba(204, 67, 0, 0.8)";
Color[13] = "rgba(3, 115, 77, 0.8)";
Color[14] = "rgba(215, 9, 71, 0.8)";
Color[15] = "rgba(119, 42, 203, 0.8)";
Color[16] = "rgba(8, 119, 131, 0.8)";
Color[17] = "rgba(37, 49, 212, 0.8)";
Color[18] = "rgba(146, 20, 115, 0.8)";
serie_color = [{
from: 0,
to: 5254,
name: '< 5 254.00',
color: Color[0]
}, {
from: 5255,
to: 10509,
name: 'From 5 255.00 to 10 509.00',
color: Color[1]
}, {
from: 10510,
to: 15764,
name: 'From 10 510.00 to 15 764.00',
color: Color[2]
}, {
from: 15765,
to: 21019,
name: 'From 15 765.00 to 21 019.00',
color: Color[3]
}, {
from: 21020,
to: 26274,
name: '> 21 020.00',
color: Color[4]
}, ];
$(function() {
var chart = Highcharts.mapChart("container", {
chart: {
backgroundColor: "#ffffff",
animation: false
},
colorAxis: [{
dataClasses: serie_color
},
{
minColor: '#efecf3',
maxColor: '#990041',
}
],
mapNavigation: {
enabled: true
},
series: [{
mapData: Highcharts.maps["bret"],
data: data,
name: "States",
borderColor: "#319663",
nullColor: "#f7f7f7",
showInLegend: true,
joinBy: ["code", "CODE_REGION"],
keys: ["CODE_REGION", "DimGraphList_0", "z", "valSize", "value", "pieOffset"]
},
{
mapData: Highcharts.maps["bret"],
type: "mapbubble",
name: "Bubbles",
colorAxis: 1,
showInLegend: true,
joinBy: ["code", "CODE_REGION"],
keys: ["CODE_REGION", "DimGraphList_0", "z", "valSize", "value", "pieOffset"],
data: data,
minSize: "5%",
maxSize: "15%"
}
]
});
});
Result is fine (https://jsfiddle.net/vegaelce/f7neq2a1/) but I've a strange behavior, when the bubble is displayed on the map, the map is is off-centered.
On the jsfiddle, if you click on the "Bubble" value in the legend (to hide them), you'll see the map move and be centered (that should be the expected right position with the bubble displayed).
Any suggestion about this move ? I suspect an offset or something else but how to find/set it ?
Another tip concerns the legend : I'd like to move the 2 legends on different points :
the legend for the first serie (colored bullet points) on the bottom of the chart
the scalar legend for the bubbles on the left (or right) of the chart
Highchart considers that there is only one legend (grouping the 2 series), is it possible to dissociate them ?
Thanks in advance
The first issue looks like a Highcharts bug (related with wrong calculation of x-axis extremes), you can report it here: https://github.com/highcharts/highcharts/issues/new/choose
As a workaround use this code:
Highcharts.seriesTypes.mapbubble.prototype.useMapGeometry = true;
Live demo: https://jsfiddle.net/BlackLabel/oL1zahtm/
As to your second question - Highcharts doesn't have built-in support for multiple legends, but you can change some legend items position by manual translatation, for example:
chart: {
...,
events: {
render: function() {
this.legend.allItems[5].legendGroup.attr({
translateX: -50,
translateY: -50
});
this.legend.allItems[6].legendGroup.attr({
translateX: -50,
translateY: -70
});
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/m7zaeLrd/

Dart - How to create a new List<Object2> from an existing List<Object1>

I have an existing List i.e.
[
{
"name": "miller",
"age": 22,
"nationality": "Romania",
"doj": "2018-09-17",
},
{
"name": "sochi",
"age": 35,
"nationality": "Poland",
"doj": "2018-10-11",
},
{
"name": "diana",
"age": 35,
"nationality": "Belarus",
"doj": "2018-12-14",
}
]
and would like to create a new List using the above list (with fewer fields) i.e.
[
{
"name": "miller",
"nationality": "Romania",
},
{
"name": "sochi",
"nationality": "Poland",
},
{
"name": "diana",
"nationality": "Belarus",
}
]
You can map the list and either remove the key that you want to be removed or copy all the keys that you want to keep.
var newList = list.map((e) => e..remove('doj'));
//or
var newList = list.map((e) => {'name': e['name'], 'age': e['age'], ...);

How to create dashed bar graph in highcharts

I have to create bar graphs as shown in the attached image using highcharts. The graph in the image has been created using Excel. But Highcharts doesn't seem to provide such feature. Though it allows to create graph using patterns but one doesn't have much control on those patterns. Can anyone please confirm if we can create similar kind of charts in highcharts or not? I have created a fiddle with highcharts for sample at http://jsfiddle.net/sandeepkparashar/6c48x39v/3/Dashed Bar Chart
As was mentioned in the comment, pattern-fill plugin can handle this.
You can create patterns and map the series, so every second column will have the corresponded pattern.
var colors = ["#FF0000", "#FF8C00", "#FFFF00", "#00FF00", "#3366FF"];
var series = [{
"color": "#FF0000",
"name": "High",
"data": [298, 199, 448, 271, 772, 494, 935, 562]
}, {
"color": "#FF8C00",
"name": "Medium High",
"data": [130, 32, 234, 172, 159, 134, 218, 160]
}, {
"color": "#FFFF00",
"name": "Medium",
"data": [141, 163, 95, 63, 71, 22, 26, 13]
}, {
"color": "#00FF00",
"name": "Medium Low",
"data": [42, 8, 34, 19, 16, 20, 21, 26]
}, {
"color": "#3366FF",
"name": "Low",
"data": [4, 4, 0, 0, 0, 0, 0, 0]
}];
function getPatterns(colors) {
return colors.map(function(color, i) {
return {
id: 'custom-pattern-' + i,
path: {
d: 'M 0 0 L 10 10 M 9 -1 L 11 1 M -1 9 L 1 11',
stroke: color
}
};
});
}
function getMappedSeries(series) {
return series.map(function(serie, i) {
return {
color: colors[i],
name: serie.name,
data: serie.data.map(function(value, j) {
return j % 2 ? {
y: value,
color: 'url(#custom-pattern-' + i + ')'
} : value;
})
};
});
}
example: http://jsfiddle.net/6c48x39v/8/
Natively, you can set border dash style for the series but you need to set dash style for the specific points, so you would have to split the series into dash/no border series or extend Highcharts.

Plotting multiple points in highchart timeseries

I have data that looks like this in JSON format. I have two data series with same time line. When I try to plot them in highstock, all my time-stamps are shown as starting in 1970s. Can anyone point me what would be wrong with my JSON format?
Reason I am not using - pointStart and pointInterval: is because sometime pointIntervals can be irregular and hence need to send in the dates.
{
"chart_data": {
"dates": [
1406876400000,
1406876700000,
1406877000000,
1406877300000,
1406877600000,
1406877900000,
1406878200000,
1406878500000,
1406878800000
],
"values": [
{
"data": [
54,
50,
62,
65,
65,
55,
51,
53,
57
]
},
{
"data": [
84,
70,
80,
78,
77,
84,
73,
83,
77
]
}
]
}
}
My Javascript method to display this data is below.
<script type="text/javascript">
$(document).ready(function() {
var chartOptions = {
chart: {
renderTo: 'chart_panel',
type: 'line',
zoomType: 'x'
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0
},
title: {text: 'Temperature & Humidity' },
subtitle: {text: 'My-Text' },
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
month: '%e. %b',
day: '%b %e',
hour: '%b %e',
year: '%b'
}
},
yAxis: {
min: 0,
title: {
text: 'Temperature (°F)/Humidity (%)'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
series: [{}],
rangeSelector : {
inputEnabled: true,
selected: '0'
},
};
var chartDataUrl = '{% url "chart_data_json" object.id %}';
function loadChart() {
$.getJSON(chartDataUrl,
function(data) {
var seriesOptions = [];
var obj1 = {};
var obj2 = {};
avgByDayOptions.xAxis.categories = data['chart_data']['dates'];
obj1.name = "Temperature";
obj1.data = data['chart_data']['values'][0]['data'];
obj2.data = data['chart_data']['values'][1]['data'];
obj2.name = "Humidity";
seriesOptions[0] = obj1;
seriesOptions[1] = obj2;
chartOptions.series = seriesOptions;
var chart = new Highcharts.StockChart( chartOptions,
function(chart){
// apply the date pickers
setTimeout(function(){
$('input.highcharts-range-selector', $('#'+chart.options.chart.renderTo))
.datepicker()
},0)
}
);
Highcharts.setOptions({ global: { useUTC: false } });
});
}
loadChart();
});
It was may bad once I passed the data in following format everything started work as expected. Just posting reply to my own question in case someone runs into similar issue?
{
"chart_data": {
"values": [
{
"data": [
[
1406851200000,
54
],
[
1406851500000,
50
],
[
1406851800000,
62
],
[
1406852100000,
65
],
[
1406852400000,
65
],
[
1406852700000,
55
],
[
1406853000000,
51
],
[
1406853300000,
53
],
[
1406853600000,
57
]
]
},
{
"data": [
[
1406851200000,
84
],
[
1406851500000,
70
],
[
1406851800000,
80
],
[
1406852100000,
78
],
[
1406852400000,
77
],
[
1406852700000,
84
],
[
1406853000000,
73
],
[
1406853300000,
83
],
[
1406853600000,
77
]
]
}
]
}
}

Three.js online editor export normal map

Im trying to use the three.js online editor to do a normal mapping experiment. The editor is great as you can see below:
Without normal map:
With normal map:
My problem when exporting, the most important thing for me is the materials but is looks like the exporter is not exporting up materials settings like shaders or uniforms:
{
"metadata": {
"version": 4,
"type": "object",
"generator": "ObjectExporter"
},
"geometries": [
{
"type": "PlaneGeometry",
"width": 200,
"height": 200,
"widthSegments": 1,
"heightSegments": 12
}],
"materials": [
{
"type": "MeshPhongMaterial",
"color": 16580351,
"ambient": 16777215,
"emissive": 0,
"specular": 13027014,
"shininess": 60,
"opacity": 1,
"transparent": false,
"wireframe": false
}],
"object": {
"type": "Scene",
"children": [
{
"name": "Plane 8",
"type": "Mesh",
"position": [-13.67,102.97,28.83],
"rotation": [-0.18,-0.22,0],
"scale": [1,1,1],
"geometry": 0,
"material": 0
},
{
"name": "AmbientLight 10",
"type": "AmbientLight",
"color": 2236962
},
{
"name": "AmbientLight 11",
"type": "AmbientLight",
"color": 2236962
},
{
"name": "DirectionalLight 12",
"type": "DirectionalLight",
"color": 16777215,
"intensity": 1,
"position": [200,200,200]
},
{
"type": "Object3D",
"position": [0,0,0],
"rotation": [0,0,0],
"scale": [1,1,1]
},
{
"type": "Object3D",
"position": [0,0,0],
"rotation": [0,0,0],
"scale": [1,1,1]
},
{
"name": "DirectionalLight 12 Target",
"type": "Object3D",
"position": [0,0,0],
"rotation": [0,0,0],
"scale": [1,1,1]
}]
}
}
I understand that the editor is work in progress so this is probably not implemented yet, but do you know if there is a way to see the generated code from the editor when building the scene? I can can see the code it should be enough for me.
Thanks :)
Sorry guys I figured how get the normal map to work, I still dont know how to see the code from the editor but I will close the question anyway... Thanks to those that took the time to read it.
//wall
var textures = {
lion: THREE.ImageUtils.loadTexture('../media/lion.png'),
lionbumpnormal: THREE.ImageUtils.loadTexture('../media/lion-bumpnormal.png')
};
// common material parameters
var ambient = 0, diffuse = 0x331100, specular = 0xffffff, shininess = 10, scale = 23;
var material = new THREE.MeshPhongMaterial( {
map: textures.lion,
normalMap: textures.lionbumpnormal,
color: 16580351,
ambient: 16777215,
emissive: 0,
specular: 13027014,
shininess: 60,
opacity: 1,
transparent: false,
wireframe: false
} );
var planeGeometry = new THREE.PlaneGeometry(10, 10);
var wall = new THREE.Mesh(
planeGeometry,
material
);
Not sure if this is what you meant, but I was trying to load a simple scene I setup in the editor. Was able to do it using THREE.ObjectLoader
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<script src="../three.js/build/three.js"></script>
<script>
(function() {
var Game = function() {
}
Game.prototype.init = function() {
var loader = new THREE.ObjectLoader();
loader.load('data.json', (function(data) {
this.scene = data;
this.load();
}).bind(this));
}
Game.prototype.draw = function() {
this.renderer.render(this.scene, this.camera);
}
Game.prototype.load = function() {
var container = document.createElement('div');
document.body.appendChild(container);
this.camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 10000);
this.camera.position.z = 500;
this.camera.position.x = 500;
this.camera.position.y = 100;
this.camera.lookAt(new THREE.Vector3(0,0,0));
this.scene.add(this.camera);
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize( window.innerWidth, window.innerHeight);
container.appendChild(this.renderer.domElement);
this.update();
};
Game.prototype.update = function() {
requestAnimationFrame(this.update.bind(this));
this.draw();
}
window.onload = function() {
var g = new Game();
g.init();
}
}).call(this);
</script>
</head>
<body>
</body>
</html>

Resources