set different bar width for each bar using ECHARTS - reactjs

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>

Related

Apexcharts how to remove markers and labels and just show the line

I have this chart. I feel those labels on the chart bring no value and distract us from seeing the actual curves. How to I remove those numbers on top of the lines?
This is my actual code, (The bit that says "markers" seems to make no difference at all).
<ReactApexChart options={{
chart: {
height: 350,
type: 'area'
},
tooltip: {
x: {
formatter: function (seriesName) {
let ano = Math.floor(seriesName/12);
let mes = seriesName%12;
return "Pagamento: " + seriesName + " - ano " + ano + " mês " + mes
},
},
},
markers: { size: 0,
colors: undefined,
strokeColors: '#fff',
strokeWidth: 2,
strokeOpacity: 0.9,
strokeDashArray: 0,
fillOpacity: 1,
discrete: [],
shape: "circle",
radius: 2,
offsetX: 0,
offsetY: 0,
onClick: undefined,
onDblClick: undefined,
showNullDataPoints: true,
hover: {
size: undefined,
sizeOffset: 3
}},
xaxis: {
type: 'numeric',
categories: categories}
}} series={[{
name: 'Sem Amortização',
data: beforeSeries
}, {
name: 'Com Amortização',
data: afterSeries,
}]} type="area" height={350} />
Edit: I thought those numbers where special markers, turns out they are labels
You can disable dataLabels.
Here is a very basic area chart without them:
let options = {
series: [{
name: 'Series',
data: [10, 20, 15]
}],
chart: {
height: 350,
type: 'area'
},
dataLabels: {
enabled: false // <--- HERE
},
xaxis: {
categories: ['Category 1', 'Category 2', 'Category 3']
}
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>

how to use dimension values in markpoints

I am using react-Echart for drawing some charts.
but I stucked some problems.
From what I read in the document, If I set proper dimension in series props, I can also use value of that dimensions in labels using formatter props.
However, even if I try many times, the formatter doesn't work properly.
Attached is the option data I used. Please check it out and give me an answer.
const option:EChartsOption = {
title: {
show: false
},
xAxis: {
show: false,
type: 'time'
},
yAxis: {
type: 'value',
position: 'right'
},
// ...
dataset:
{
dimensions: [
'date', 'randomV', 'dailyIncome', 'dailyOutcome', 'percent'
],
source: fakeLineGraphData // [{date:string, randomV:number, dailyIncome: number, dailyOutcome:number , percent: number}]
},
series: [{
dimensions: ['date', 'randomV'],
type: 'line',
symbol: 'none',
showSymbol: false,
markPoint: {
itemStyle: {
color: '#74d527'
},
data: [
{
type: 'max',
name: 'Max',
symbol: 'triangle',
symbolSize: 10,
symbolRotate: 180,
symbolOffset: [0, -20],
label: {
position: 'right',
formatter: `max {c} ({#percent}%)`, // don't works!
color: 'gray'
}
},
{
type: 'min',
name: 'Min',
symbol: 'triangle',
symbolSize: 10,
symbolOffset: [0, 20],
label: {
position: 'right',
formatter: `최저 {c} (-${#percent}%)`, // don't works!
color: 'gray'
}
}
]
},
//...
]
};
Doc which I refered : https://echarts.apache.org/en/option.html#series-line.markPoint.label.formatter

chartjs: bars smaller than actual column, tooltip doesn't display

As you can see my bars are not covering the entire width of the label 'column'.
My tooltip only shows if I am exactly hovering the bar, or, if I remove the bars, exactly on the line point.
options: {
plugins: {
legend: { display: false },
title: { display: false },
tooltip: {
displayColors: false, backgroundColor: '#ffffff',
bodyColor: '#595f69', bodyFont: {size: 14},
borderColor: '#595f69', borderWidth: 1,
titleFont: {size: 0}
}
},
responsive: true, aspectRatio: 4,
scales: {
y: { display: true, suggestedMin: 0, suggestedMax: 80, ticks: { stepSize: 20 } },
y1: {display: false, suggestedMin: 0, suggestedMax: 80, ticks: { stepSize: 2 }},
x: { grid: { drawBorder: false, display: false } }
I tried plugins like chartjs crosshair, but don't manage to make it work with typescript.
How can I make it so that anywhere my mouse hover in the label 'column' area, the tooltip displays?
You can set the intersect property to false to always get the tooltip without needing to intersect the bar exactly:
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
}]
},
options: {
plugins: {
tooltip: {
intersect: false
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.js"></script>
</body>
You can make your own tooltip by editing the callbacks, i had to get the nearest values around my cursor, from all datasets, on my line chart. this works for me on Chartjs 2.9.3:
tooltips: {
mode: "x",
position: "nearest",
intersect: false,
callbacks: {
beforeBody: function(tooltipItems, allData) {
let x = tooltipItems[0].x; // get x coordinate
let datasets = allData.datasets; // datasets
let values = [];
for (i in datasets) {
let dataset = datasets[i];
let meta = this._chart.getDatasetMeta(i); // dataset metadata
let xScale = this._chart.scales[meta.xAxisID]; // dataset's x axis
let xValue = xScale.getValueForPixel(x); // we get the x value on the x axis with x coordinate
let data = dataset.data // data
// search data for the first value with a bigger x value
let index = data.findIndex(function(o) {
return o.x >= xValue;
});
let value = data[index]; // this is our nearest value
// format label
if (isNaN(value.ymax)) {
values.push(`${dataset.label}: ${value.y}\n`);
} else {
values.push(`${dataset.label}: ${value.y}, min: ${value.ymin}, max: ${value.ymax}\n`)
}
}
return values.join(""); // return label
},
label: function() { // this needs to be empty
},
}
},

Echarts 3.6.2 Legend Type "scroll" does not be applied correctly

In my angularJs project,I have a pie Echarts and I define it like below.The problem is that I may have lots of legend and I see I can use type:'scroll' to make it from here, but I failed and it has no impact.
$scope.pieEcharts1 = {
option: {
title: {
text: 'MyPieChart',
left: 'left',
},
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
legend: {
orient: 'vertical',
left: 'right',
type:'scroll',//does not work
data: []
},
label: {
normal: {
show: true,
formatter: '{d}%'
}
},
labelLine: {
normal: {
show: true
}
},
series: [{
name: 'MyData',
type: 'pie',
radius: '62%',
center: ['50%', '50%'],
data: [],
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
}
}
}
//http request to get data
$scope.pieEcharts1.option.legend.data = nameArray
$scope.pieEcharts1.option.series[0] = dataArray
What is the problem in my code?
The scrollable legned is supported from v3.7.0.
https://echarts.apache.org/zh/changelog.html#v3-7-0

RGraph V5 Upgrade - error getting context

I had a working 3d chart using version 2107-10-1 that used images for the y axis.
I'm now trying to use the version 5 libraries but I'm getting an error:
"Cannot read property 'getContext' of null at new RGraph.Drawing.Image (RGraph.drawing.image.js:64)
Which is:
"context = this.canvas.getContext('2d');"
I change the line in the library to 3d to match the chart variant setting of 3d and the error is resolved. However I then get the following errors:
"Cannot set property 'shadowColor' of null
at Object.RG.noShadow.RG.NoShadow (RGraph.common.core.js:5155)
at RGraph.Drawing.Image.draw.Draw (RGraph.drawing.image.js:490)"
I've been going through the API to try and find any differences to the property names but my skill and understanding is not great.
Any help or advice would be greatly appreciated.
:-)
new RGraph.Bar({
id: 'cvs',
data: [ [0,5,5],[0,5,5],[0,5,5] ],
options: {
/******/
variant: '3d',
variantThreedAngle: 0,
hmarginGrouped: 2,
/*****/
textFont: '"Courier New", Courier, monospace',
titleFont: '"Courier New", Courier, monospace',
labels:['Monday', 'Saturday', 'Sunday'] ,
colors: [ '#3cb44b','#5484ed','#fbd75b' ],
textSize: 11,
title: 'Test Learner1: T1C1 W/B 22nd April 2019',
titleSize: 11,
titleColor:'#338833',
titleX: 50,
titleY: 25,
titleHalign: 'Left',
textAccessible: false,
key: ['LabelOne','LabelTwo','LabelThree'], //['One','Two','Three','Four','Five'],
keyPositionY: 470,
keyPositionX: 0,
gutterBottom: 65,
gutterRight: 10,
gutterTop: 40,
gutterLeft: 70,
keyPosition: 'gutter',
keyTextSize: 9,
numyticks: 2,
ylabelsCount: 2,
ymax: 10,
ymin: 0,
backgroundColor: 'white',
labelsColor: 'green'
// end options
}
}).draw().exec(function (obj)
{
var images = [
'smileyimages/graphimages/smiley5.png','smileyimages/graphimages/smiley10.png','smileyimages/graphimages/smiley1.png',
];
var index = 0;
obj.coordsText.forEach(function (val, key, arr)
{
if (val.tag === 'scale') {
var x = val.x,
y = val.y,
text = val.text;
var img = new RGraph.Drawing.Image({
id: 'cvs',
x: x,
y: y,
src: images[index],
options: {
halign: 'right',
valign: 'center'
}
}).draw();
index++;
}
});
obj.set({
ylabels: true
});
RGraph.redraw();
}).on('beforedraw', function (obj)
{
RGraph.clear(obj.canvas, 'white');
});
I've adjusted your code for the new property names. With this code remember to update the paths to the images.
<script src="/libraries/RGraph.drawing.image.js"></script>
<script src="/libraries/RGraph.common.core.js"></script>
<script src="/libraries/RGraph.common.key.js"></script>
<script src="/libraries/RGraph.bar.js"></script>
And the code that makes the chart:
new RGraph.Bar({
id: 'cvs',
data: [ [1,5,5],[1,5,5],[1,5,5] ],
options: {
variant: '3d',
hmargin: 20,
hmarginGrouped: 2,
textFont: '"Courier New", Courier, monospace',
titleFont: '"Courier New", Courier, monospace',
xaxis: false,
xaxisLabels:['Monday', 'Saturday', 'Sunday'] ,
colors: [ '#3cb44b','#5484ed','#fbd75b' ],
title: 'Test Learner1: T1C1 W/B 22nd April 2019',
titleX: 120,
titleY: 25,
titleHalign: 'Left',
textAccessible: false,
key: ['LabelOne','LabelTwo','LabelThree'], //['One','Two','Three','Four','Five'],
keyPositionY: 435,
keyPositionX: 100,
marginBottom: 95,
marginRight: 10,
marginTop: 40,
marginLeft: 100,
keyPosition: 'margin',
keyLabelsSize: 9,
yaxis: false,
yaxisLabelsCount: 2,
yaxisScaleMax: 10,
yaxisScaleMin: 0,
backgroundColor: 'white',
xaxisLabelsColor: 'green'
}
}).draw().exec(function (obj)
{
var images = [
'/images/alex.png',
'/images/alert.png',
'/images/facebook.png'
];
var index = 0;
obj.coordsText.forEach(function (val, key, arr)
{
if (val.tag === 'scale') {
var x = val.x,
y = val.y,
text = val.text;
var img = new RGraph.Drawing.Image({
id: 'cvs',
x: x,
y: y + 10,
src: images[index++],
options: {
halign: 'right',
valign: 'center'
}
}).draw();
}
});
});

Resources