sencha touch: real time chart - charts

i am using sencha touch to show a chart and add data to store of chart dynamically.but when i add data to store, my chart does not update result.
this is code of my chart:
Ext.define('MyApp.view.MyLineChart1', {
extend: 'Ext.chart.CartesianChart',
requires: [
'Ext.chart.axis.Category',
'Ext.chart.axis.Numeric',
'Ext.chart.series.Line'
],
config: {
itemId: 'xy',
store: 'MyStore',
colors: [
'#115fa6',
'#94ae0a',
'#a61120',
'#ff8809',
'#ffd13e',
'#a61187',
'#24ad9a',
'#7c7474',
'#a66111'
],
axes: [
{
type: 'category',
fields: [
'x'
],
maximum: 5,
minimum: 0
},
{
type: 'numeric',
fields: [
'y'
],
grid: {
odd: {
fill: '#e8e8e8'
}
},
position: 'left'
}
],
series: [
{
type: 'line',
colors: 'rgba(0,200,0,0.3)',
style: {
smooth: true,
stroke: 'rgb(0,200,0)',
},
xField: 'x',
yField: 'y'
}
],
listeners: [
{
fn: 'onChartShow',
event: 'show',
order: 'after'
}
]
},
onChartShow: function(component, eOpts) {
var TaskRunner = Ext.create("MyApp.controller.TaskRunner");
chart = Ext.ComponentQuery.query("#xy")[0];
store = chart.getStore();
chart.animationSuspended = true;
chart.update();
store.removeAll();
this.timeChartTask = TaskRunner.start({
run: this.update_chart,
interval: 1000,
repeat: 10,
scope: this
});
},
update_chart: function(chart) {
var me = this;
chart = Ext.ComponentQuery.query("#xy")[0];
store = chart.getStore();
count = store.getCount();
xAxis = chart.getAxes()[0];
visibleRange = 10000;
second = 1000;
console.log(xAxis.getMinimum());
if (count > 0) {
lastRecord = store.getAt(count - 1);
xValue = lastRecord.get('x') + second;
if (xValue - me.startTime > visibleRange) {
me.startTime = xValue - visibleRange;
xAxis.setMinimum(this.startTime);
xAxis.setMaximum(xValue);
console.log("count >0");
}
store.add({
x: xValue,
y: me.getNextValue()
});
// store.load();
chart.redraw();
} else {
chart.animationSuspended = true;
me.startTime = Math.floor(Ext.Date.now() / second) * second;
xAxis.setMinimum(me.startTime);
xAxis.setMaximum(me.startTime + visibleRange);
store.add({
x: this.startTime,
y: me.getNextValue()
});
chart.animationSuspended = false;
// store.load();
chart.redraw();
console.log("count < 0");
}
},
getNextValue: function(previousValue) {
var delta = Math.random()*4 - 2;
if (Ext.isNumber(previousValue)) {
return Ext.Number.constrain(previousValue + delta, -2, 2);
}
return Math.random()*4 - 2;
}
});
this is my store:
Ext.define('MyApp.store.MyStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.MyModel1'
],
config: {
model: 'MyApp.model.MyModel1',
storeId: 'MyStore'
}
});
and this is my model:
Ext.define('MyApp.model.MyModel1', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.Field'
],
config: {
fields: [
{
name: 'x'
},
{
name: 'y'
}
]
}
});

If you want set data to store use this code:
var store = Ext.getStore('MyStore');
store.load(function () {
var store = Ext.getStore('MyStore');
store.removeAll();
store.add({
x: xValue,
y: me.getNextValue()
});
store.sync();
});

Related

Is there any way to downplay toolbox custom feature button on another feature button

Two custom feature added in toolbox. I need functionality where in we can reset one feature on click of another.
like existing feature 'zoom' button and 'horizontally select' brush button. If we click the zoom button first and then click on brush button then zoom button automatically gets reset to default.
below is the reference code -
`function func(x) {
x /= 10;
return Math.random() * 22;
}
function generateData() {
let data = [];
for (let i = 0; i <= 10; i += 0.1) {
data.push([i, func(i)]);
}
return data;
}
var isPointSelect = false;
var rangeSelector = false;
option = {
animation: false,
toolbox: {
feature: {
dataZoom: {
yAxisIndex: false
},
myRangeSelector: {
show: true,
title: 'Range Selector',
icon: 'path://M432.45,595.444c0,2.177-4.661,6.82-11.305,6.82c-6.475,0-11.306-4.567-11.306-6.82s4.852-6.812,11.306-6.812C427.841,588.632,432.452,593.191,432.45,595.444L432.45,595.444z M421.155,589.876c-3.009,0-5.448,2.495-5.448,5.572s2.439,5.572,5.448,5.572c3.01,0,5.449-2.495,5.449-5.572C426.604,592.371,424.165,589.876,421.155,589.876L421.155,589.876z M421.146,591.891c-1.916,0-3.47,1.589-3.47,3.549c0,1.959,1.554,3.548,3.47,3.548s3.469-1.589,3.469-3.548C424.614,593.479,423.062,591.891,421.146,591.891L421.146,591.891zM421.146,591.891',
onclick: function (model, api, type) {
// debugger;
rangeSelector = !rangeSelector;
this.model.setIconStatus(type, rangeSelector ? 'emphasis' : 'normal');
}
},
myPointSelect: {
show: true,
title: 'Point Select',
icon: 'path://M432.45,595.444c0,2.177-4.689,6.82-11.305,6.82r-6.475,0-11.306-4.567-11.306-6.82s4.852-6.812,11.306-6.812C427.841,588.632,432.452,593.191,432.45,595.444L432.45,595.444z M421.155,589.876c-3.009,0-5.448,2.495-5.448,5.572s2.439,5.572,5.448,5.572c3.01,0,5.449-2.495,5.449-5.572C426.604,592.371,424.165,589.876,421.155,589.876L421.155,589.876z M621.146,591.294c-1.916,0-3.47,1.589-3.47,3.549c0,1.959,1.554,3.548,3.47,3.548s3.469-1.589,3.469-3.548C424.614,593.479,423.062,591.891,421.146,591.891L421.146,591.891zM421.146,591.891',
onclick: function (model, api, type) {
isPointSelect = !isPointSelect;
this.model.setIconStatus(type, isPointSelect ? 'emphasis' : 'normal');
}
},
brush: {
type: ['lineX', 'clear', 'keep']
}
}
},
brush: {
xAxisIndex: 'all',
brushLink: 'all',
brushStyle: {
color: 'white'
},
outOfBrush: {
colorAlpha: 0.1
}
},
graphic: {
elements: []
},
grid: {
top: 100,
left: 50,
right: 40,
bottom: 50
},
xAxis: {
minorTick: {
show: true
},
minorSplitLine: {
show: true
}
},
yAxis: {
minorTick: {
show: true
},
minorSplitLine: {
show: true
}
},
series: [
{
type: 'line',
showSymbol: false,
clip: true,
data: generateData(),
markArea: {
data: []
}
}
]
};`
Echart has similar functionality for zoom and brush feature.

echarts stacked bar chart with time xaxis

Can someone check my chart options and suggest a way to make the time xaxis behave correctly? I've tried with timestamps, dates, timestamps / 1000 and nothing looks right
let sales = [
0,84,5,3,2,1,0,0,3,6
]
let listings = [
1,297,23,5,8,6,9,3,6,19
]
let ps = [
1663084060653,
1663089644329,
1663095228005,
1663100811680,
1663106395356,
1663111979032,
1663117562708,
1663123146384,
1663128730059,
1663134313735
]
let color = "red"
option = {
textStyle: {
color
},
legend: {
textStyle: {
color
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'time',
data: ps,
// axisLabel: {
// formatter: ts => new Date(ts).toTimeString().replace(/ .*/, '')
// }
}
],
yAxis: [
{
// type: 'value'
}
],
series: [
{
name: 'Sales',
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: sales
},
{
name: "Listings",
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: listings
}
]
}
Your series (listings & sales here) have to have a [date, value] format. Also, you'll have to remove data from xAxis as it will automatically follow the dates that are given in the series.
So, in your example :
//convert listings & sales to a list of [date, value]
listings = listings.map((value, index) => {
return [ps[index], value]
})
sales = sales.map((value, index) => {
return [ps[index], value]
})
xAxis: [
{
type: 'time',
//data: ps, <--- remove this line
}
],

Echarts. How update two series in realtimie chart?

I have realtime chart https://codepen.io/xnkka/pen/qBdNpmo, which has two series, updating with setOption work only to one of the series. How fix this?
myChart.setOption({
xAxis: {
data: startDataCat,
},
series: [{
data: startDataVal
},
{
data: startDataVal2
},
]
});
Just checked your code, seems like you have missed to remove the value from second dataset. You forgot to add the below statement where you remove the data from front of second dataset.
startDataVal2.shift();
I have updated your code and made the following post.
var myChart = echarts.init(document.getElementById('main'));
var dataCount = 500;
var data = generateData(dataCount);
var data2 = generateData(dataCount);
var startDataCat = data.categoryData.slice(0, 250);
var endDataCat = data.categoryData.slice(250);
var startDataVal = data.valueData.slice(0, 250);
var startDataVal2 = data2.valueData.slice(0, 250);
var endDataVal = data.valueData.slice(250);
var endDataVal2 = data2.valueData.slice(250);
var option = {
title: {
text: "live chart",//
left: 10
},
toolbox: {
feature: {
dataZoom: {
yAxisIndex: false
},
saveAsImage: {
pixelRatio: 2
}
}
},
legend: {
data: ['first', 'second'],
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
bottom: 90
},
dataZoom: [{
type: 'inside'
}, {
type: 'slider'
}],
xAxis: {
data: startDataCat,
silent: false,
splitLine: {
show: false
},
splitArea: {
show: false
}
},
yAxis: {
splitArea: {
show: false
}
},
series: [{
name: 'first',
type: 'line',
data: startDataVal,
// Set `large` for large data amount
large: true
},
{
name: 'second',
type: 'line',
data: startDataVal2,
// Set `large` for large data amount
large: true
}
]
};
setInterval(function () {
startDataCat.shift();
startDataCat.push(endDataCat.shift())
startDataVal.shift();
startDataVal2.shift();
startDataVal.push(endDataVal.shift())
startDataVal2.push(endDataVal2.shift())
myChart.setOption({
xAxis: {
data: startDataCat,
},
series: [{
data: startDataVal
},
{
data: startDataVal2
},
]
});
}, 1000);
function generateData(count) {
var baseValue = Math.random() * 1000;
var time = +new Date(2020, 1, 1);
var smallBaseValue;
function next(idx) {
smallBaseValue = idx % 30 === 0
? Math.random() * 700
: (smallBaseValue + Math.random() * 500 - 250);
baseValue += Math.random() * 20 - 10;
return Math.max(
0,
Math.round(baseValue + smallBaseValue) + 3000
);
}
var categoryData = [];
var valueData = [];
for (var i = 0; i < count; i++) {
categoryData.push(echarts.format.formatTime('yyyy-MM-dd\nhh:mm:ss', time));
valueData.push(next(i).toFixed(2));
time += 1000;
}
return {
categoryData: categoryData,
valueData: valueData
};
}
myChart.setOption(option)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="main" style="width:1000px; height:400px;"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.6.0/echarts.min.js"></script>
</body>
</html>

Highmaps mappies with drilldown

I need to do a drilldown of mappies, from country to states:
https://www.highcharts.com/maps/demo/map-pies
Actually I am using a custom map from Peru, but already with the example of USA would help me a lot showing me some solution.
Is it possible to do this?
I've made an example with mappie and drilldown to show you how to start and achieve it. I've added drilldown for California so only this state will work.
Add drilldown module: https://code.highcharts.com/maps/modules/drilldown.js
Each point should have a drilldown property set. You can add it to a point object or to data array (then keys array in series should point to it. API: https://api.highcharts.com/highmaps/plotOptions.series.keys)
When drilldown event occurs hide or remove each mappie series and create it again on drillup event.
Code:
// New map-pie series type that also allows lat/lon as center option.
// Also adds a sizeFormatter option to the series, to allow dynamic sizing
// of the pies.
Highcharts.seriesType('mappie', 'pie', {
center: null, // Can't be array by default anymore
clip: true, // For map navigation
states: {
hover: {
halo: {
size: 5
}
}
},
dataLabels: {
enabled: false
}
}, {
getCenter: function() {
var options = this.options,
chart = this.chart,
slicingRoom = 2 * (options.slicedOffset || 0);
if (!options.center) {
options.center = [null, null]; // Do the default here instead
}
// Handle lat/lon support
if (options.center.lat !== undefined) {
var point = chart.fromLatLonToPoint(options.center);
options.center = [
chart.xAxis[0].toPixels(point.x, true),
chart.yAxis[0].toPixels(point.y, true)
];
}
// Handle dynamic size
if (options.sizeFormatter) {
options.size = options.sizeFormatter.call(this);
}
// Call parent function
var result = Highcharts.seriesTypes.pie.prototype.getCenter.call(this);
// Must correct for slicing room to get exact pixel pos
result[0] -= slicingRoom;
result[1] -= slicingRoom;
return result;
},
translate: function(p) {
this.options.center = this.userOptions.center;
this.center = this.getCenter();
return Highcharts.seriesTypes.pie.prototype.translate.call(this, p);
}
});
var data = [
// state, demVotes, repVotes, libVotes, grnVotes, sumVotes, winner, offset config for pies
['Alabama', 729547, 1318255, 44467, 9391, 2101660, -1],
['Alaska', 116454, 163387, 18725, 5735, 304301, -1],
['Arizona', 1161167, 1252401, 106327, 34345, 2554240, -1],
['Arkansas', 380494, 684782, 29829, 9473, 1104578, -1],
['California', 8577206, 4390272, 467370, 271047, 13705895, 1, {
lon: -1,
drawConnector: false
}, 'us-ca'],
['Colorado', 1338870, 1202484, 144121, 38437, 2723912, 1],
['Connecticut', 897572, 673215, 48676, 22841, 1642304, 1, {
lat: -1.5,
lon: 1
}],
['Delaware', 235603, 185127, 14757, 6103, 441590, 1, {
lat: -1.3,
lon: 2
}],
['District of Columbia', 282830, 12723, 4906, 4258, 304717, 1, {
lat: -2,
lon: 2
}],
['Florida', 4504975, 4617886, 207043, 64399, 9394303, -1],
['Georgia', 1877963, 2089104, 125306, 0, 4092373, -1],
['Hawaii', 266891, 128847, 15954, 12737, 424429, 1, {
lat: -0.5,
lon: 0.5,
drawConnector: false
}],
['Idaho', 189765, 409055, 28331, 8496, 635647, -1],
['Illinois', 2977498, 2118179, 208682, 74112, 5378471, 1],
['Indiana', 1039126, 1557286, 133993, 7841, 2738246, -1],
['Iowa', 653669, 800983, 59186, 11479, 1525317, -1],
['Kansas', 427005, 671018, 55406, 23506, 1176935, -1],
['Kentucky', 628854, 1202971, 53752, 13913, 1899490, -1],
['Louisiana', 780154, 1178638, 37978, 14031, 2010801, -1],
['Maine', 352156, 332418, 37578, 13995, 736147, 1],
['Maryland', 1502820, 878615, 78225, 33380, 2493040, 1, {
lon: 0.6,
drawConnector: false
}],
['Massachusetts', 1995196, 1090893, 138018, 47661, 3271768, 1, {
lon: 3
}],
['Michigan', 2268839, 2279543, 172136, 51463, 4771981, -1],
['Minnesota', 1367716, 1322951, 112972, 36985, 2840624, 1, {
lon: -1,
drawConnector: false
}],
['Mississippi', 462127, 678284, 14411, 3595, 1158417, -1],
['Missouri', 1054889, 1585753, 96404, 25086, 2762132, -1],
['Montana', 174281, 273879, 28036, 7868, 484064, -1],
['Nebraska', 273185, 485372, 38746, 8337, 805640, -1],
['Nevada', 539260, 512058, 37384, 0, 1088702, 1],
['New Hampshire', 348526, 345790, 30694, 6465, 731475, 1],
['New Jersey', 1967444, 1509688, 72143, 37131, 3586406, 1, {
lat: -1,
lon: 1.2
}],
['New Mexico', 380923, 316134, 74544, 9797, 781398, 1],
['New York', 4145376, 2638135, 162273, 100110, 7045894, 1],
['North Carolina', 2169496, 2345235, 130021, 1038, 4645790, -1],
['North Dakota', 93758, 216794, 21434, 378, 332364, -1],
['Ohio', 2320596, 2776683, 174266, 44310, 5315855, -1],
['Oklahoma', 420375, 949136, 83481, 0, 1452992, -1],
['Oregon', 991580, 774080, 93875, 49247, 1908782, 1],
['Pennsylvania', 2874136, 2945302, 144826, 49334, 6013598, -1],
['Rhode Island', 227062, 166454, 14700, 6171, 414387, 1, {
lat: -0.7,
lon: 1.7
}],
['South Carolina', 855373, 1155389, 49204, 13034, 2073000, -1],
['South Dakota', 117442, 227701, 20845, 0, 365988, -1],
['Tennessee', 868853, 1519926, 70286, 15952, 2475017, -1],
['Texas', 3877868, 4685047, 283492, 71558, 8917965, -1],
['Utah', 222858, 375006, 39608, 7695, 645167, -1],
['Vermont', 178573, 95369, 10078, 6758, 290778, 1, {
lat: 2
}],
['Virginia', 1981473, 1769443, 118274, 27638, 3896828, 1],
['Washington', 1727840, 1210370, 160356, 57571, 3156137, 1],
['West Virginia', 187519, 486304, 22958, 8016, 704797, -1],
['Wisconsin', 1382947, 1407028, 106470, 31016, 2927461, -1],
['Wyoming', 55973, 174419, 13287, 2515, 246194, -1]
],
maxVotes = 0,
demColor = 'rgba(74,131,240,0.80)',
repColor = 'rgba(220,71,71,0.80)',
libColor = 'rgba(240,190,50,0.80)',
grnColor = 'rgba(90,200,90,0.80)';
// Compute max votes to find relative sizes of bubbles
Highcharts.each(data, function(row) {
maxVotes = Math.max(maxVotes, row[5]);
});
// Build the chart
var chart = Highcharts.mapChart('container', {
chart: {
animation: false, // Disable animation, especially for zooming
events: {
load: function() {
addMapPie(this);
},
drilldown: function(e) {
if (!e.seriesOptions) {
var chart = this,
mapKey = 'countries/us/' + e.point.drilldown + '-all',
// Handle error, the timeout is cleared on success
fail = setTimeout(function() {
if (!Highcharts.maps[mapKey]) {
chart.showLoading('<i class="icon-frown"></i> Failed loading ' + e.point.name);
fail = setTimeout(function() {
chart.hideLoading();
}, 1000);
}
}, 3000);
// Show the spinner
chart.showLoading('<i class="icon-spinner icon-spin icon-3x"></i>'); // Font Awesome spinner
// Load the drilldown map
$.getScript('https://code.highcharts.com/mapdata/' + mapKey + '.js', function() {
data = Highcharts.geojson(Highcharts.maps[mapKey]);
// Set a non-random bogus value
$.each(data, function(i) {
this.value = i;
});
chart.series.forEach(function(s) {
if (s.options.type === 'mappie') {
s.hide();
}
});
// Hide loading and add series
chart.hideLoading();
clearTimeout(fail);
chart.addSeriesAsDrilldown(e.point, {
name: e.point.name,
data: data,
dataLabels: {
enabled: true,
format: '{point.name}'
}
});
});
}
this.setTitle(null, {
text: e.point.name
});
},
drillup: function() {
this.setTitle(null, {
text: ''
});
this.series.forEach(function(s) {
if (s.options.type === 'mappie') {
s.show();
}
});
}
}
},
title: {
text: 'USA 2016 Presidential Election Results'
},
colorAxis: {
dataClasses: [{
from: -1,
to: 0,
color: 'rgba(244,91,91,0.5)',
name: 'Republican'
}, {
from: 0,
to: 1,
color: 'rgba(124,181,236,0.5)',
name: 'Democrat'
}, {
from: 2,
to: 3,
name: 'Libertarian',
color: libColor
}, {
from: 3,
to: 4,
name: 'Green',
color: grnColor
}]
},
mapNavigation: {
enabled: true
},
// Limit zoom range
yAxis: {
minRange: 2300
},
tooltip: {
useHTML: true
},
// Default options for the pies
plotOptions: {
mappie: {
borderColor: 'rgba(255,255,255,0.4)',
borderWidth: 1,
tooltip: {
headerFormat: ''
}
}
},
series: [{
mapData: Highcharts.maps['countries/us/us-all'],
data: data,
name: 'States',
borderColor: '#FFF',
showInLegend: false,
joinBy: ['name', 'id'],
keys: ['id', 'demVotes', 'repVotes', 'libVotes', 'grnVotes',
'sumVotes', 'value', 'pieOffset', 'drilldown'
],
tooltip: {
headerFormat: '',
pointFormatter: function() {
var hoverVotes = this.hoverVotes; // Used by pie only
return '<b>' + this.id + ' votes</b><br/>' +
Highcharts.map([
['Democrats', this.demVotes, demColor],
['Republicans', this.repVotes, repColor],
['Libertarians', this.libVotes, libColor],
['Green', this.grnVotes, grnColor]
].sort(function(a, b) {
return b[1] - a[1]; // Sort tooltip by most votes
}), function(line) {
return '<span style="color:' + line[2] +
// Colorized bullet
'">\u25CF</span> ' +
// Party and votes
(line[0] === hoverVotes ? '<b>' : '') +
line[0] + ': ' +
Highcharts.numberFormat(line[1], 0) +
(line[0] === hoverVotes ? '</b>' : '') +
'<br/>';
}).join('') +
'<hr/>Total: ' + Highcharts.numberFormat(this.sumVotes, 0);
}
}
}, {
name: 'Separators',
type: 'mapline',
data: Highcharts.geojson(Highcharts.maps['countries/us/us-all'], 'mapline'),
color: '#707070',
showInLegend: false,
enableMouseTracking: false
}, {
name: 'Connectors',
type: 'mapline',
color: 'rgba(130, 130, 130, 0.5)',
zIndex: 5,
showInLegend: false,
enableMouseTracking: false
}],
drilldown: {
activeDataLabelStyle: {
color: '#FFFFFF',
textDecoration: 'none',
textOutline: '1px #000000'
},
drillUpButton: {
relativeTo: 'spacingBox',
position: {
x: 0,
y: 60
}
}
}
});
function addMapPie(chart) {
// Add the pies after chart load, optionally with offset and connectors
Highcharts.each(chart.series[0].points, function(state) {
if (!state.id) {
return; // Skip points with no data, if any
}
var pieOffset = state.pieOffset || {},
centerLat = parseFloat(state.properties.latitude),
centerLon = parseFloat(state.properties.longitude);
// Add the pie for this state
chart.addSeries({
type: 'mappie',
name: state.id,
zIndex: 6, // Keep pies above connector lines
sizeFormatter: function() {
var yAxis = this.chart.yAxis[0],
zoomFactor = (yAxis.dataMax - yAxis.dataMin) /
(yAxis.max - yAxis.min);
return Math.max(
this.chart.chartWidth / 45 * zoomFactor, // Min size
this.chart.chartWidth / 11 * zoomFactor * state.sumVotes / maxVotes
);
},
tooltip: {
// Use the state tooltip for the pies as well
pointFormatter: function() {
return state.series.tooltipOptions.pointFormatter.call({
id: state.id,
hoverVotes: this.name,
demVotes: state.demVotes,
repVotes: state.repVotes,
libVotes: state.libVotes,
grnVotes: state.grnVotes,
sumVotes: state.sumVotes
});
}
},
data: [{
name: 'Democrats',
y: state.demVotes,
color: demColor
}, {
name: 'Republicans',
y: state.repVotes,
color: repColor
}, {
name: 'Libertarians',
y: state.libVotes,
color: libColor
}, {
name: 'Green',
y: state.grnVotes,
color: grnColor
}],
center: {
lat: centerLat + (pieOffset.lat || 0),
lon: centerLon + (pieOffset.lon || 0)
}
}, false);
// Draw connector to state center if the pie has been offset
if (pieOffset.drawConnector !== false) {
var centerPoint = chart.fromLatLonToPoint({
lat: centerLat,
lon: centerLon
}),
offsetPoint = chart.fromLatLonToPoint({
lat: centerLat + (pieOffset.lat || 0),
lon: centerLon + (pieOffset.lon || 0)
});
chart.series[2].addPoint({
name: state.id,
path: 'M' + offsetPoint.x + ' ' + offsetPoint.y +
'L' + centerPoint.x + ' ' + centerPoint.y
}, false);
}
});
// Only redraw once all pies and connectors have been added
chart.redraw();
}
#container {
min-width: 320px;
max-width: 800px;
height: 500px;
margin: 1em auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.15/proj4.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/maps/modules/map.js"></script>
<script src="https://code.highcharts.com/maps/modules/data.js"></script>
<script src="https://code.highcharts.com/maps/modules/drilldown.js"></script>
<script src="https://code.highcharts.com/maps/modules/exporting.js"></script>
<script src="https://code.highcharts.com/maps/modules/offline-exporting.js"></script>
<script src="https://code.highcharts.com/mapdata/countries/us/us-all.js"></script>
<link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
<div id="container"></div>
Demo:
https://jsfiddle.net/BlackLabel/1d845opk/1/
EDIT
To add mappies also to the first level of drilldown you have to remove mappies series form the main view of the map when drilldown event occurs and create new ones for drilled data. It's quite difficult to explain exactly how to make it, so I prepared an example where each drilled level has sample data (you can get them from a server the same as drilled map data). I hope this example will help and you will see what's going on there.
Demo:
http://jsfiddle.net/BlackLabel/zLcnby79/
Thank you Wojciech Chmiel !
I did my map with the help of your post.
// New map-pie series type that also allows lat/lon as center option.
// Also adds a sizeFormatter option to the series, to allow dynamic sizing
// of the pies.
Highcharts.seriesType('mappie', 'pie', {
center: null, // Can't be array by default anymore
clip: true, // For map navigation
states: {
hover: {
halo: {
size: 5
}
}
},
dataLabels: {
enabled: false
}
}, {
getCenter: function() {
var options = this.options,
chart = this.chart,
slicingRoom = 2 * (options.slicedOffset || 0);
if (!options.center) {
options.center = [null, null]; // Do the default here instead
}
// Replace lat/lon with plotX/plotY
if (options.center.plotX !== undefined) {
options.center = [options.center.plotX, options.center.plotY];
}
// Handle dynamic size
if (options.sizeFormatter) {
options.size = options.sizeFormatter.call(this);
}
// Call parent function
var result = Highcharts.seriesTypes.pie.prototype.getCenter.call(this);
// Must correct for slicing room to get exact pixel pos
result[0] -= slicingRoom;
result[1] -= slicingRoom;
return result;
},
translate: function (p) {
this.options.center = this.userOptions.center;
this.center = this.getCenter();
return Highcharts.seriesTypes.pie.prototype.translate.call(this, p);
}
});
var data = [
// state, demVotes, repVotes, libVotes, grnVotes, sumVotes, winner, drilldown
['CAPLINA-OCONA', 729547, 1318255, 44467, 9391, 2101660, -1, 'aaa01'],
['CHAPARRA-CHINCHA', 116454, 163387, 18725, 5735, 304301, -1, 'aaa02'],
['CANETE-FORTALEZA', 1161167, 1252401, 106327, 34345, 2554240, -1, 'aaa03'],
['HUARMEY-CHICAMA', 380494, 684782, 29829, 9473, 1104578, -1, 'aaa04'],
['JEQUETEPEQUE-ZARUMILLA', 8577206, 4390272, 467370, 271047, 13705895, 1, 'aaa05'],
['MARANON', 1338870, 1202484, 144121, 38437, 2723912, 1, 'aaa06'],
['AMAZONAS', 897572, 673215, 48676, 22841, 1642304, 1, 'aaa07'],
['HUALLAGA', 235603, 185127, 14757, 6103, 441590, 1, 'aaa08'],
['UCAYALI', 282830, 12723, 4906, 4258, 304717, 1, 'aaa09'],
['MANTARO', 4504975, 4617886, 207043, 64399, 9394303, -1, 'aaa10'],
['PAMPAS-APURIMAC', 1877963, 2089104, 125306, 0, 4092373, -1, 'aaa11'],
['URUBAMBA-VILCANOTA', 266891, 128847, 15954, 12737, 424429, 1, 'aaa12'],
['MADRE DE DIOS', 189765, 409055, 28331, 8496, 635647, -1, 'aaa13'],
['TITICACA', 2977498, 2118179, 208682, 74112, 5378471, 1, 'aaa14']
],
maxVotes = 0,
demColor = 'rgba(74,131,240,0.80)',
repColor = 'rgba(220,71,71,0.80)',
libColor = 'rgba(240,190,50,0.80)',
grnColor = 'rgba(90,200,90,0.80)';
// Compute max votes to find relative sizes of bubbles
Highcharts.each(data, function(row) {
maxVotes = Math.max(maxVotes, row[5]);
});
// Build the chart
var chart = Highcharts.mapChart('container', {
chart: {
animation: false, // Disable animation, especially for zooming
events: {
load: function() {
addMapPie(this);
},
drilldown: function(e) {
if (!e.seriesOptions) {
var chart = this,
//mapKey = 'countries/us/' + e.point.drilldown + '-all',
mapKey = 'paises/pe/' + e.point.drilldown,
ruta = e.point.drilldown,
// Handle error, the timeout is cleared on success
fail = setTimeout(function() {
if (!Highcharts.maps[mapKey]) {
chart.showLoading('<i class="icon-frown"></i> Failed loading ' + e.point.name);
fail = setTimeout(function() {
chart.hideLoading();
}, 1000);
}
}, 3000);
// Show the spinner
chart.showLoading('<i class="icon-spinner icon-spin icon-3x"></i>'); // Font Awesome spinner
// Load the drilldown map
//$.getScript('https://code.highcharts.com/mapdata/' + mapKey + '.js', function() {
//$.getScript('http://test1.ana.gob.pe/prueba-mappies/' + ruta + '.js', function () {
$.getScript('https://aplicaciones01.ana.gob.pe/mappies/' + ruta + '.js', function () {
data = Highcharts.geojson(Highcharts.maps[mapKey]);
// Set a non-random bogus value
$.each(data, function(i) {
this.value = i;
});
chart.series.forEach(function(s) {
if (s.options.type === 'mappie') {
s.hide();
}
});
// Hide loading and add series
chart.hideLoading();
clearTimeout(fail);
chart.addSeriesAsDrilldown(e.point, {
name: e.point.name,
data: data,
dataLabels: {
enabled: true,
format: '{point.name}'
}
});
});
}
this.setTitle(null, {
text: e.point.name
});
},
drillup: function() {
this.setTitle(null, {
text: ''
});
this.series.forEach(function(s) {
if (s.options.type === 'mappie') {
s.show();
}
});
}
}
},
title: {
text: 'Resultados'
},
colorAxis: {
dataClasses: [{
from: -1,
to: 0,
color: 'rgba(244,91,91,0.5)',
name: 'Republican'
}, {
from: 0,
to: 1,
color: 'rgba(124,181,236,0.5)',
name: 'Democrat'
}, {
from: 2,
to: 3,
name: 'Libertarian',
color: libColor
}, {
from: 3,
to: 4,
name: 'Green',
color: grnColor
}]
},
mapNavigation: {
enabled: true //Para el zoom (+ -)
},
// Limit zoom range
yAxis: {
minRange: 2300
},
tooltip: {
useHTML: true
},
// Default options for the pies
plotOptions: {
mappie: {
borderColor: 'rgba(255,255,255,0.4)',
borderWidth: 1,
tooltip: {
headerFormat: ''
}
}
},
series: [{
mapData: Highcharts.maps['paises/pe/aaa-all'],
data: data,
name: 'States',
borderColor: '#FFF',
showInLegend: false,
joinBy: ['name', 'id'],
//keys: ['id', 'demVotes', 'repVotes', 'libVotes', 'grnVotes',
// 'sumVotes', 'value', 'pieOffset'],
keys: ['id', 'demVotes', 'repVotes', 'libVotes', 'grnVotes', 'sumVotes', 'value', 'drilldown'],
tooltip: {
headerFormat: '',
pointFormatter: function () {
var hoverVotes = this.hoverVotes; // Used by pie only
return '<b>' + this.id + ' votes</b><br/>' +
Highcharts.map([
['Democrats', this.demVotes, demColor],
['Republicans', this.repVotes, repColor],
['Libertarians', this.libVotes, libColor],
['Green', this.grnVotes, grnColor]
].sort(function (a, b) {
return b[1] - a[1]; // Sort tooltip by most votes
}), function (line) {
return '<span style="color:' + line[2] +
// Colorized bullet
'">\u25CF</span> ' +
// Party and votes
(line[0] === hoverVotes ? '<b>' : '') +
line[0] + ': ' +
Highcharts.numberFormat(line[1], 0) +
(line[0] === hoverVotes ? '</b>' : '') +
'<br/>';
}).join('') +
'<hr/>Total: ' + Highcharts.numberFormat(this.sumVotes, 0);
}
}
}],
drilldown: {
activeDataLabelStyle: {
color: '#FFFFFF',
textDecoration: 'none',
textOutline: '1px #000000'
},
drillUpButton: {
relativeTo: 'spacingBox',
position: {
x: 0,
y: 60
}
}
}
});
function addMapPie(chart) {
// Add the pies after chart load, optionally with offset and connectors
Highcharts.each(chart.series[0].points, function(state) {
//if (!state.id) {
if (!state.id || !state.properties) {
return; // Skip points with no data, if any
}
var pieOffset = state.pieOffset || {},
centerLat = parseFloat(state.properties.latitude),
centerLon = parseFloat(state.properties.longitude);
// Add the pie for this state
chart.addSeries({
type: 'mappie',
name: state.id,
zIndex: 6, // Keep pies above connector lines
sizeFormatter: function () {
var yAxis = this.chart.yAxis[0],
zoomFactor = (yAxis.dataMax - yAxis.dataMin) /
(yAxis.max - yAxis.min);
return Math.max(
this.chart.chartWidth / 45 * zoomFactor, // Min size
this.chart.chartWidth / 11 * zoomFactor * state.sumVotes / maxVotes
);
},
/*****/
tooltip: {
// Use the state tooltip for the pies as well
pointFormatter: function () {
return state.series.tooltipOptions.pointFormatter.call({
id: state.id,
hoverVotes: this.name,
demVotes: state.demVotes,
repVotes: state.repVotes,
libVotes: state.libVotes,
grnVotes: state.grnVotes,
sumVotes: state.sumVotes
});
}
},
data: [{
name: 'Democrats',
y: state.demVotes,
color: demColor
}, {
name: 'Republicans',
y: state.repVotes,
color: repColor
}, {
name: 'Libertarians',
y: state.libVotes,
color: libColor
}, {
name: 'Green',
y: state.grnVotes,
color: grnColor
}],
center: {
/*lat: centerLat + (pieOffset.lat || 0),
lon: centerLon + (pieOffset.lon || 0)*/
plotX: state.plotX,
plotY: state.plotY
}
}, false);
});
// Only redraw once all pies and connectors have been added
chart.redraw();
}
#container {
min-width: 320px;
max-width: 800px;
height: 500px;
margin: 1em auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.15/proj4.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/maps/modules/map.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<script src="https://code.highcharts.com/modules/drilldown.js"></script>
<script src="https://code.highcharts.com/maps/modules/exporting.js"></script>
<script src="https://code.highcharts.com/maps/modules/offline-exporting.js"></script>
<script src="https://aplicaciones01.ana.gob.pe/mappies/AAA_psad56_simp.js"></script>
<link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
<div id="container"></div>
Here:
- https://jsfiddle.net/JMarcia/w06k5zog/17/

Highcharts :Donut chart overlaps data labels

I'm working on a donut chart type, with the Highcharts library.
As you can see in the image below, some of the inner data labels are overlapped.
I've been playing with the parameter "distance" but doesn't fix this.
Find attached the code below,
// Create the chart
$(container).highcharts({
chart: {
type: 'pie'
},
credits: {
enabled: false
},
exporting: {
buttons: {
contextButton: {
symbol: 'url(/icon-turn-down.png)'
}
}
},
title: {
text: _title,
margin: 50
},
plotOptions: {
pie: {
shadow: false,
center: ['50%', '50%']
}
},
tooltip: {
formatter: function() {
var s = this.point.name.split('.');
if (s.length == 1) {
return this.y > 1? '<b>'+this.point.name+':</b> '+Highcharts.numberFormat(this.point.y) : null;
}
return this.y > 1? s[0]+'<br /><b>'+$.trim(s[1])+':</b> '+Highcharts.numberFormat(this.point.y) : null;
}
},
series: [{
name: '',
data: innerData,
size: '80%',
dataLabels: {
formatter: function() {
return this.y > 0 ? this.point.name : null;
},
color: 'white',
distance: -50
}
}, {
name: '',
data: outerData,
size: '100%',
innerSize: '80%',
dataLabels: {
formatter: function() {
var s = this.point.name.split('.');
if (s.length == 1) {
return this.y > 1 ? '<b>'+ this.point.name+':</b> '+ Highcharts.numberFormat(this.point.y) : null ;
}
s = this.point.name.substring(this.point.name.indexOf(".")+2);
return this.y > 1 ? '<b>'+ s+':</b> '+ Highcharts.numberFormat(this.point.y): null;
},
style: {
fontSize: "10px",
fontColor: "#000000"
}
}
}]
});
Finally, I found a solution, which is playing with the "startangle" attribute.
series: [{
name: '',
data: innerData,
startAngle:110,
size: '80%',
dataLabels: {
formatter: function() {
return this.y > 0 ? this.point.name : null;
},
color: 'white',
distance: -45
}, {
...
Distance parameter cannot be applied for each point, only general, so only what comes to my mind is iteared on each datalabel and use translate() function, or use formatter, apply CSS class and dhten use top/left parameter for each element. But will be helpful if you recreate your example as fiddle.