Highchart + Extjs + chart Updates - extjs

I setup this jsfiddle to show you an issue regarding Extjs and Highchart:
http://jsfiddle.net/xea0w8n3/21/
var store = new Ext.data.ArrayStore({
fields: ['month', 'value'],
data : [
['jan', 1],
['feb', 2],
['mar', 3],
['apr', 4],
['mai', 5],
['jun', 6],
['jul', 16],
['aug', 2],
['sep', 7],
['oct', 4],
['nov', 3],
['dec', 11]
]
});
var chart = Ext.create('Chart.ux.Highcharts', {
id:'chart',
series:[{
dataIndex: 'value'
}],
xField: 'month',
store: store,
chartConfig: {
chart: {
type: 'spline'
},
title: {
text: 'A simple graph'
},
xAxis: {
plotLines: [{
color: '#FF0000',
width: 5,
value: 'mar'
}]
}
}
});
store.load();
Ext.create('Ext.window.Window', {
title: 'Highchart Testing',
id:'window',
closable : true,
width: 300,
height: 400,
layout:'fit',
anchor:'100%',
items:[chart],
tbar:[
{
xtype:'button',
text:'Add PlotLine',
handler: function(){
Ext.getCmp('chart').chart.yAxis[0].addPlotLine({
value:'12',
width: '2',
dashStyle: 'longdashdot',
color: 'red'
});
}
}
]
}).show();
If I add a Plot Line and resize the window the line disappear :(
Any ideas to keep the plotline while window is open?
Thanks in advance!
Regards

I've had a similar issue with the line disappearing when I move the window. Does that also happen for you? I worked around the problem by hiding and showing the chart on the window's move event. It is a bit silly but it worked for me.
listeners: {
// For me it was the move event
resize: function (window) {
var chart = Ext.getCmp('chart');
chart.hide();
chart.show();
}
}

Related

How to move outside pie chart labels on angular apexcharts.js

I'm trying to move the labels out of the pie chart, but I can't move them in any way, is there any way i angular to move them out of the pie chart? (Angular v14)
I don't quite understand the documentation so it would be great if someone could help me understand how to do this.
Typescript code:
#ViewChild('chart') chart!: ChartComponent;
public chartOptions: Partial<ChartOptions>;
constructor() {
this.chartOptions = {
series: [45, 50, 22],
chart: {
type: 'pie',
width: '270px',
},
labels: ['Team A', 'Team B', 'Team C'],
responsive: [
{
breakpoint: 480,
options: {
chart: {
width: 100,
},
},
},
],
legend: {
show: true,
position: 'bottom',
horizontalAlign: 'center',
},
dataLabels: {
offSetY: 50,
// add this part to remove %
enabled: true,
},
};
}
HTML Code:
<div class="chartContainer" style="width: 30%;">
<apx-chart
[series]="chartOptions.series"
[chart]="chartOptions.chart"
[labels]="chartOptions.labels"
[responsive]="chartOptions.responsive"
[legend]="chartOptions.legend"
[dataLabels]="chartOptions.dataLabels">
</apx-chart>
</div>
I tried to put "offset", "offsetY", etc, inside the datalabel, but they didn't move an inch
You can tweak dataLabels and plotOptions.pie.dataLabels in your chartOptions. I give you a basic example (without Angular for practical reasons...):
let options = {
series: [45, 50, 22],
chart: {
type: 'pie',
height: 350
},
labels: ['Team A', 'Team B', 'Team C'],
dataLabels: {
style: {
colors: ['black']
}
},
plotOptions: {
pie: {
dataLabels: {
offset: 60
}
}
}
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>

set different bar width for each bar using ECHARTS

Im using the e-charts libary for creating a bar chart for my data .
like so :
option.series = [
{
name: 'buy',
type: 'bar',
stack: 'one',
data: Object.values(chartData?.data || {}).map(elem => -elem.buy?.total),
color: colors.bought,
label: {
show: true,
position: "bottom",
formatter: (value) => Math.round(Math.abs(value.data))
},
tooltip: {
formatter: (data) => Math.abs(data.value).toString()
},
// barWidth:this.data
},
{
name: 'sell',
type: 'bar',
stack: 'one',
data: Object.values(chartData?.data || {}).map(elem =>elem.sell?.total),
color: colors.sold,
label: {
show: true,
position: "top",
formatter: (value) => Math.round(Math.abs(value.data))
},
tooltip: {
formatter: (data) => Math.abs(data.value).toString()
},
},
{
name: 'profite',
type: 'bar',
stack: 'two',
barGap: '-100%',
z: 100,
data: Object.values(chartData?.data || {}).map(elem => elem.sell?.profit),
color: colors.profit,
label: {
show: true,
position: "insideTop",
textBorderWidth: -1,
offset: [0, -20],
formatter: (value) => Math.round(Math.abs(value.data))
},
tooltip: {
formatter: (data) => Math.abs(data.value).toString()
},
},
]
im trying to set a different width for each bar depending on the value of each bar .
on data property i get a list of numbers rendering .
When i try to add a barWidth property all i can do is change all of the bars in the same chrts like so for example:
barWidth: ${getBarWidth((Object.values(chartData?.data || {}).map((elem) => elem.sell?.amount)))}%
so i returne a different value of my data each time but it didnt changed each bar according to its value (either buy, sell and so on).
Thanks in adavance.
As you pointed out, barWidth sets the width of all the bars of a bar series. And I don't think there is a way to set the width of each bar in the same bar series.
What you should use instead is a custom series.
Custom series have a parameter called renderItem, where you write the render logic of the chart. It's where you'll be able to display custom shapes (custom sized bar in your case), using graphics.
Here is an example I found on their website, doing pretty much what you're looking for.
var container = document.getElementById('main');
var chart = echarts.init(container);
const colorList = [
'#4f81bd',
'#c0504d',
'#9bbb59',
'#604a7b',
'#948a54',
'#e46c0b'
];
const data = [
[10, 16, 3, 'A'],
[16, 18, 15, 'B'],
[18, 26, 12, 'C'],
[26, 32, 22, 'D'],
[32, 56, 7, 'E'],
[56, 62, 17, 'F']
].map(function (item, index) {
return {
value: item,
itemStyle: {
color: colorList[index]
}
};
});
chart.setOption({
title: {
text: 'Profit',
left: 'center'
},
tooltip: {},
xAxis: {
scale: true
},
yAxis: {},
series: [
{
type: 'custom',
renderItem: function (params, api) {
var yValue = api.value(2);
var start = api.coord([api.value(0), yValue]);
var size = api.size([api.value(1) - api.value(0), yValue]);
var style = api.style();
return {
type: 'rect',
shape: {
x: start[0],
y: start[1],
width: size[0],
height: size[1]
},
style: style
};
},
label: {
show: true,
position: 'top'
},
dimensions: ['from', 'to', 'profit'],
encode: {
x: [0, 1],
y: 2,
tooltip: [0, 1, 2],
itemName: 3
},
data: data
}
]
});
#main {
width: 600px;
height: 400px;
}
<html>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.3.2/echarts.min.js"></script>
<div id="main"></div>
</body>
</html>

Adding tooltip to legend in highcharts

I am trying to add a tooltip to the legend in highcharts. I am using a pie chart. Using angular js framework.
The legend code is as below
legend: {
useHTML: true,
layout: 'vertical',
align: 'left',
itemMarginTop: 10,
itemMarginBottom: 15,
title: {
style: {
fontSize: "14px",
fontWeight: "600",
color: "#404040"
}
},
itemStyle: {
fontWeight: 'normal',
color: '#404040',
fontSize: '14px'
},
//x : 70,
//y: 110,
labelFormatter: function() {
return ` <md-icon>
<md-tooltip md-direction="top">Hello</md-tooltip>
<i class="material-icons help_icon">info_outline</i>
</md-icon>`
}
},
I do not get the expected results. it just displays the letter H and no icon. If i use a standalone icon like
<i class="material-icons help_icon">info_outline</i>
It just displays the icon. But I am unable to add any tooltip. I searched online and found a solution using the jquery UI plugin. Is there any other way without the plugin and using the angular material icons? Please suggest.
Ps: I have also tried with single quotes / double quotes instead of inverted ticks.
Unfortunately, tooltip in a legend is not supported. However, you can create it using Highcharts.SVGRenderer. Check code and demo posted below.
Code:
var chart = Highcharts.chart('container', {
chart: {
type: 'column',
events: {
load: function() {
var chart = this,
legend = chart.legend,
legendItems = legend.allItems,
group,
rectElem,
textElem,
box,
i;
group = chart.renderer.g('legend-tooltip').attr({
transform: 'translate(-9999, -9999)',
zIndex: 99
}).add();
textElem = chart.renderer.text().attr({
class: 'legend-tooltip-text',
zIndex: 7
}).add(group);
rectElem = chart.renderer.rect().attr({
'class': 'legend-tooltip',
'stroke-width': 1,
'stroke': '#c5c5c5',
'fill': 'rgba(245, 245, 245, 0.95)',
}).add(group);
for (i = 0; i < legendItems.length; i++) {
(function(i) {
var item = legend.allItems[i].legendItem.parentGroup;
item.on('mouseover', function(e) {
// Define legend-tooltip text
var str = chart.series[i].userOptions.fullName;
textElem.element.innerHTML = str;
// Adjust rect size to text
box = textElem.getBBox()
rectElem.attr({
x: box.x - 8,
y: box.y - 5,
width: box.width + 15,
height: box.height + 10
});
// Show tooltip
group.attr({
transform: `translate(${e.clientX + 7}, ${e.clientY + 7})`
})
}).on('mouseout', function(e) {
// Hide tooltip
group.attr({
transform: 'translate(-9999,-9999)'
})
});
})(i);
}
}
}
},
series: [{
data: [10, 12, 5],
fullName: 'Series 1 tooltip'
}, {
data: [6, 10, 7],
fullName: 'Series 2 tooltip'
}]
});
Demo:
https://jsfiddle.net/BlackLabel/3cbpe0mn/
API reference:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer
https://api.highcharts.com/class-reference/Highcharts.SVGElement#on

How to create overlapping bar charts in angular js?

i have trying to create a chart like
this. I have tried with highchart.js and chart.js but result is not like expected. Is there any plugin to create a chart like this? Or any other way to stack like this in highchart.js or in chart.js? Thank you.
You can use highcharts Fixed placement columns that is inverted. Check the demo posted below.
HTML:
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
JS:
Highcharts.chart('container', {
chart: {
type: 'column',
inverted: true
},
xAxis: {
categories: [
'Seattle HQ',
'San Francisco',
'Tokyo'
]
},
yAxis: [{
min: 0,
title: {
text: 'Employees'
}
}, {
title: {
text: 'Profit (millions)'
},
opposite: true
}],
legend: {
shadow: false
},
tooltip: {
shared: true
},
plotOptions: {
column: {
grouping: false,
shadow: false,
borderWidth: 0
}
},
series: [{
name: 'Employees',
color: 'rgba(165,170,217,1)',
data: [150, 73, 20],
pointPadding: 0,
groupPadding: 0.15,
pointPlacement: 0
}, {
name: 'Employees Optimized',
color: 'rgba(126,86,134,.9)',
data: [140, 90, 40],
pointPadding: 0.2,
pointPlacement: 0
}]
});
Demo:
https://jsfiddle.net/BlackLabel/g0b9uev5/1/

Using ExtJS 4 charts in ExtJS 3 application

I'm trying to add Ext4 charting to an existing Ext3 application, using ext-all-sandbox.js. I've got the basics working, but the code below gives axis.processView is not a function. It works fine without the axes defined (but with no axes obviously).
It appears that the config objects are being used directly instead of being used to create actual axis instances. Any solutions to get this working?
TestGraphPanel = Ext.extend(Ext.Panel, {
initComponent: function() {
TestGraphPanel.superclass.initComponent.call(this);
Ext4.define('DataPoint', {
extend: 'Ext.data.Model',
fields: ['xValue', 'yValue']
});
this.store = Ext4.create('Ext.data.Store', {
model: 'DataPoint',
data: [
{xValue: 0, yValue: 2},
{xValue: 1, yValue: 4},
{xValue: 2, yValue: 7},
{xValue: 3, yValue: 5},
{xValue: 4, yValue: 8},
{xValue: 5, yValue: 9}
]
});
},
afterRender: function() {
Ext4.create('Ext.chart.Chart', {
renderTo: this.body.dom,
width: this.ownerCt.getWidth(),
height: this.ownerCt.getHeight(),
store: this.store,
axes: [
{
title: 'x',
type: 'Numeric',
postition: 'bottom',
fields: ['xValue']
},
{
title: 'y',
type: 'Numeric',
position: 'left',
fields: ['yValue']
}
],
series: [
{
type: 'line',
xField: 'xValue',
yField: 'yValue'
}
]
});
}
});
After a quick look at the source, I think your problem might come from the fact that you're creating your chart in the afterRender.
I'm thinking of those lines in particular
//process all views (aggregated data etc) on stores
//before rendering.
me.axes.each(function(axis) {
axis.processView();
});
The config objects are parsed just before. Otherwise try to set a breakpoint in there and check the objects.

Resources