In Apache Echarts, when using multiple pie charts (e.g. nested pies, or even side-by-side pies), how do we add a title to each pie to signify what the pie represents? While the "title" option can accept an array of titles, there isn't a good way to position them so that they are above, within or in some other way related to the respective pies they are meant to label. It's as if there's a missing concept of a seriesLabel / seriesTitle that sits conceptually between the chart title and the individual item labels.
Series item labels are already in use for the items (pie slices) so cannot be used with position: center, and that wouldn't help with nested pies anyway since there's only room for one label at the center.
Here are my nested pies. I used an image editor to add labels where I might want them - hugging the pies they each label. That's what I'm trying to accomplish.
I do not understand what is your problem with the array of titles...
Here is a simple example showing how to give a title to each pie:
const data = [
{
name: 'Foo',
value: 10
},
{
name: 'Bar',
value: 20
},
{
name: 'Baz',
value: 15
}
];
let option = {
title: [
{
text: 'Pie 1',
subtext: 'Left',
left: '46px',
textAlign: 'center'
},
{
text: 'Pie 2',
subtext: 'Center',
left: '146px',
textAlign: 'center'
},
{
text: 'Pie 3',
subtext: 'Right',
left: '246px',
textAlign: 'center'
}
],
series: [
{
type: 'pie',
radius: '42px',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
left: 0,
right: '66%',
top: 0,
bottom: 0
},
{
type: 'pie',
radius: '42px',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
left: '33%',
right: '33%',
top: 0,
bottom: 0
},
{
type: 'pie',
radius: '42px',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
left: '66%',
right: 0,
top: 0,
bottom: 0
}
]
};
let myChart = echarts.init(document.getElementById('main'));
myChart.setOption(option);
#main {
width: 300px;
height: 200px;
}
<script src="https://cdn.jsdelivr.net/npm/echarts#5.4.1/dist/echarts.min.js"></script>
<div id="main"></div>
EDIT 1
Same example with nested pies:
const data = [
{
name: 'Foo',
value: 10
},
{
name: 'Bar',
value: 20
},
{
name: 'Baz',
value: 15
}
];
let option = {
title: [
{
text: 'Pie 1',
left: '48%',
textAlign: 'center'
},
{
text: 'Pie 2',
left: '48%',
top: '26%',
textAlign: 'center'
}
],
series: [
{
type: 'pie',
radius: ['120px', '90px'],
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
top: '10px'
},
{
type: 'pie',
radius: '42px',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
top: '10px'
}
]
};
let myChart = echarts.init(document.getElementById('main'));
myChart.setOption(option);
#main {
width: 300px;
height: 300px;
}
<script src="https://cdn.jsdelivr.net/npm/echarts#5.4.1/dist/echarts.min.js"></script>
<div id="main"></div>
EDIT 2
If you want something completely responsive with nested pies, indeed, I do not know the recipe using a simple array of titles...
But you can do this somehow creating two containers, which means each pie will be in its own <canvas> element. Then you can use CSS to give your inner pie an absolute position.
There is extra work to handle the behavior of both charts on resize. Your <canvas> elements should always be squares. In other words, their width and height should stay equal.
When you resize the window, you have to get its width and height to determine if you have a horizontal display or a vertical one. In both cases, take the smallest value and resize outer and inner containers (width and height) with it. You can even get a variable font size thanks to this value.
Of course, you should avoid px in your options. Prefer % instead.
Here is the code:
const data = [
{
name: 'Foo',
value: 10
},
{
name: 'Bar',
value: 20
},
{
name: 'Baz',
value: 15
}
];
let outerOption = {
title: {
text: 'Pie 1',
top: '2%',
left: '50%',
textAlign: 'center'
},
series: [
{
type: 'pie',
radius: ['100%', '80%'],
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
top: '10%'
}
]
};
let innerOption = {
title: {
text: 'Pie 2',
top: '25%',
left: '50%',
textAlign: 'center'
},
series: [
{
type: 'pie',
radius: '50%',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
top: '10%'
}
]
};
let outerChart = echarts.init(document.getElementById('outer')),
innerChart = echarts.init(document.getElementById('inner'));
outerChart.setOption(outerOption);
innerChart.setOption(innerOption);
function resize(container, size) {
container.resize({
width: size,
height: size
});
container.setOption({
title: {
textStyle: {
fontSize: Math.round(size / 20)
}
}
});
}
['load', 'resize'].forEach(event => {
window.addEventListener(event, () => {
let width = window.innerWidth,
height = window.innerHeight,
size = width;
if (width > height) {
size = height;
}
resize(outerChart, size);
resize(innerChart, size);
});
});
body {
margin: 0;
}
#outer, #inner {
width: 100vh;
height: 100vh;
}
#inner {
position: absolute;
top: 0;
left: 0;
}
<script src="https://cdn.jsdelivr.net/npm/echarts#5.4.1/dist/echarts.min.js"></script>
<div id="outer"></div>
<div id="inner"></div>
Related
I'm able to add a graphic to an EChart and center it in the canvas. But I can only make it a fixed width - I want it to scale when the chart resizes. Can see an example here:
https://codepen.io/bennyb/pen/qBKPWNM
option = {
tooltip: {
trigger: "item"
},
legend: {
bottom: 20,
left: "center"
},
graphic: [
{
id: 'img',
type: "image",
top: 'center',
left: 'center',
style: {
image: "http://cdn.onlinewebfonts.com/svg/img_155117.png",
width: 200,
height: 200
}
}
],
series: [
{
name: "Let vs Available",
type: "pie",
color: [
"#00ABAB",
"#007680"
],
radius: [
"45%",
"70%"
],
avoidLabelOverlap: false,
label: {
show: false,
position: "center"
},
emphasis: {
label: {
show: true,
fontSize: "15",
fontWeight: "bold"
}
},
labelLine: {
show: true
},
data: [
{
value: 31,
name: "Let"
},
{
value: 69,
name: "Available"
}
]
}
]
}
I'm able to add an id to the graphic, is there a way I can target that to resize the image on update?
I try to chanage a color of line lables:
exmaple of label pic
The line has settings:
const linedataset = {
type: 'line',
label: 'label',
data: xavarage,
order: 1,
borderColor: 'rgb(225, 54, 54)',
backgroundColor: lineBackground,
};
And common settings are:
const chartoptions = {
hoverBackgroundColor,
backgroundColor,
responsive: true,
scales: {
x: {},
y: {
min: 0,
},
},
plugins: {
title: {
display: true,
text: this.selectedCategory?.full,
font: {
size: 20,
},
},
datalabels: {
anchor: 'end',
align: 'end',
},
},
};
I have tried to usse the following code:
options: {
legend: {
color: "#ccc"
}
}
But it does not work too. How to set color of label text (line graphic)?
Your chart uses chartjs-plugin-datalabels. Therefore, you need to define color inside datalabels as follows:
datalabels: {
color: '#ccc',
anchor: 'end',
align: 'end'
},
I want to display the following image instead of Label in a gauge chart:
<?xml version="1.0" encoding="UTF-8"?>
<svg width="33.614mm" height="23.031mm" version="1.1" viewBox="0 0 33.614 23.031" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(-34.286 -116.77)">
<path
d="m35.218 128.28 2.6458-10.583 2.6458 10.583 2.6458 10.583 5.2916-21.166 5.2916 21.166 5.2916-21.166 5.2916 21.166 2.6458-10.583v0"
fill="none" stroke="#000" stroke-linecap="round"
stroke-linejoin="round" stroke-width="1.865"
/>
</g>
</svg>
Here is the chart:
option = {
series: [
{
type: 'gauge',
startAngle: 200,
endAngle: -20,
center: ['50%', '70%'],
axisLine: {
lineStyle: {
width: 8,
color: [
[0.3, 'red'],
[0.7, 'orange'],
[1, '#96BE0F']
]
}
},
pointer: {
itemStyle: {
color: 'auto'
}
},
axisTick: {
distance: -15,
length: 5,
lineStyle: {
color: '#fff',
width: 1
}
},
splitLine: {
distance: -15,
length: 8,
lineStyle: {
color: '#fff',
width: 2
}
},
axisLabel: {
color: 'auto',
distance: -20,
fontSize: 12
},
detail: {
valueAnimation: true,
formatter: '{value} %',
color: 'auto',
},
data: [
{
value: 50,
name: 'Label',
// image: 'path://m57.046 134.9v-13.229m3.9688 12.7h2.6458v-12.171h-2.6458m-22.49 12.7h18.521v2.6458l3.9687 1e-5 1e-6 -18.521h-3.9688v2.6458h-18.521v0h-1e-6'
}
],
title: {
fontSize: 20,
fontWeight: 800,
fontFamily: 'Arial',
color: 'grey',
offsetCenter: [0, '-70%'],
// image: 'path://m57.046 134.9v-13.229m3.9688 12.7h2.6458v-12.171h-2.6458m-22.49 12.7h18.521v2.6458l3.9687 1e-5 1e-6 -18.521h-3.9688v2.6458h-18.521v0h-1e-6'
},
}
]
};
I want to insert that image with fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.865".
I only could output the image in a pictorial chart, but even then I could not make it not to fill anything.
Update
I was able to output a PNG image using graphic, but not an SVG. Has anyone have a clue why? How can I output an SVG image?
option = {
xAxis: {show: false},
yAxis: {show: false},
series: [
{
type: 'gauge',
startAngle: 200,
endAngle: -20,
center: ['50%', '70%'],
axisLine: {
lineStyle: {
width: 8,
color: [
[0.3, 'red'],
[0.7, 'orange'],
[1, '#96BE0F']
]
}
},
pointer: {
itemStyle: {
color: 'auto'
}
},
axisTick: {
distance: -15,
length: 5,
lineStyle: {
color: '#fff',
width: 1
}
},
splitLine: {
distance: -15,
length: 8,
lineStyle: {
color: '#fff',
width: 2
}
},
axisLabel: {
color: 'auto',
distance: -20,
fontSize: 12
},
detail: {
valueAnimation: true,
formatter: '{value} %',
color: 'auto'
},
data: [50]
},
],
graphic: {
type: 'image',
left: 'center',
bottom: 495,
offsetCenter: [0, '-60%'],
style: {
image: 'https://i.imgur.com/4KIo3sb.png',
// image: 'path://M29.902,23.275c1.86,0,3.368-1.506,3.368-3.365c0-1.859-1.508-3.365-3.368-3.365 c-1.857,0-3.365,1.506-3.365,3.365C26.537,21.769,28.045,23.275,29.902,23.275z M36.867,30.74c-1.666-0.467-3.799-1.6-4.732-4.199 c-0.932-2.6-3.131-2.998-4.797-2.998s-7.098,3.894-7.098,3.894c-1.133,1.001-2.1,6.502-0.967,6.769 c1.133,0.269,1.266-1.533,1.934-3.599c0.666-2.065,3.797-3.466,3.797-3.466s0.201,2.467-0.398,3.866 c-0.599,1.399-1.133,2.866-1.467,6.198s-1.6,3.665-3.799,6.266c-2.199,2.598-0.6,3.797,0.398,3.664 c1.002-0.133,5.865-5.598,6.398-6.998c0.533-1.397,0.668-3.732,0.668-3.732s0,0,2.199,1.867c2.199,1.865,2.332,4.6,2.998,7.73 s2.332,0.934,2.332-0.467c0-1.401,0.269-5.465-1-7.064c-1.265-1.6-3.73-3.465-3.73-5.265s1.199-3.732,1.199-3.732 c0.332,1.667,3.335,3.065,5.599,3.399C38.668,33.206,38.533,31.207,36.867,30.74z',
width: 80
}
}
}
I am trying to create a scrollbar like the one below using echarts
So far I have managed to get the scroll using dataZoom feature but I haven't been able to style it like a normal scroll bar.
const dataY = [
'a',
'b',
'v',
'd',
'e',
'f',
'x',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n'
]; // 名称
const dataX = [
20, 50, 15, 35, 50, 30, 40, 50, 60, 20, 50, 15, 35, 50, 30, 40, 50, 60
]; // 数据
option = {
backgroundColor: '#1C1C1C',
grid: {
top: '10%',
right: '10%',
left: '10%',
bottom: '10%'
},
yAxis: [
{
type: 'category',
data: dataY,
axisLine: {
lineStyle: {
color: '#333333'
}
},
axisLabel: {
interval: 0,
margin: 10,
color: '#999999',
textStyle: {
fontSize: 11
},
rotate: '0'
},
axisTick: {
show: false
}
}
],
xAxis: [
{
axisLabel: {
padding: [3, 0, 0, 0],
formatter: '{value}',
color: '#999999',
textStyle: {
fontSize: 11
}
},
axisTick: {
show: true
},
axisLine: {
lineStyle: {
color: '#333333'
}
},
splitLine: {
lineStyle: {
color: '#333333'
}
}
}
],
dataZoom: [
{
type: 'slider',
yAxisIndex: 0,
zoomLock: true,
width: 5,
right: 10,
top: '10%',
bottom: '10%',
start: 70,
end: 20,
brushSelect: false,
handleSize: '60%',
showDetail: false,
backgroundColor: '#000',
borderColor: '#000',
opacity: 1,
brushStyle: false,
handleStyle: {
color: '#FF6700',
borderColor: '#FF6700'
}
},
{
type: 'inside',
id: 'insideY',
yAxisIndex: 0,
start: 15,
end: 20,
zoomOnMouseWheel: false,
moveOnMouseMove: true,
moveOnMouseWheel: true,
backgroundColor: 'transparent'
}
],
series: [
{
type: 'bar',
data: dataX,
barWidth: '5',
itemStyle: {
normal: {
color: '#FF6700',
shadowBlur: 4,
borderRadius: 100
}
},
label: {
normal: {
show: false,
lineHeight: 4,
formatter: '{c}',
position: 'top',
textStyle: {
color: '#fff',
fontSize: 10
}
}
}
}
]
};
I am left with a weird scrollbar that works as it should be unfortunately looks really weird.
I had the exact same issue as you, and i found a turnaround.
Instead of using the datazoom from ECharts as a scrollbar, you can just use the overflow of the div of the chart, and you can costumize it as you want with css. First you need to comment or delete the part of the datazoom in you code and change the html and css as this:
<div class="grid" [style.width.%]="100" [style.height.%]="100" #wrapper>
<div class="ChartDiv" echarts [options]="options" [style.width.px]="ganttWidth" [style.height.px]="ganttHeight"></div>
</div>
Then you just have to define the css like this:
.grid {
overflow-y: scroll !important;
//hidden if you dont want the x-Axis to have a scroll
overflow-x: hidden !important;
}
//Change the css as you want
::-webkit-scrollbar {
width: 16px;
}
::-webkit-scrollbar-track {
background-color: #e4e4e4;
border-radius: 100px;
}
With this code, your graph will have this aspect:
Now you just need to change your css as you want the style of this xD.
I'm having trouble on getting the events to work on my chart. I need to get the value of selected area of my parallel coordinates chart. I tried using chartDataRangeSelected but it does nothing when I select some data.
Here's my code:
<div echarts [options]="chartOption" class="demo-chart" (chartInit)="onChartInit($event)" (chartDataRangeSelected)="onChartSelect($event)"></div>
Chart config:
chartOption: EChartOption = {
title: {
text: 'Demo Parallel Coordinates',
subtext: 'data from macrofocus',
left: 'center',
top: 5,
itemGap: 0,
textStyle: {
color: '#000000'
},
z: 200
},
parallelAxis: this.makeParallelAxis(this.schema),
grid: [{
show: true,
left: 0,
right: 0,
top: '0',
bottom: 0,
borderColor: 'transparent',
backgroundColor: 'white',
z: 99
}],
parallel: {
top: '10%',
left: 100,
right: 100,
bottom: 100,
axisExpandable: true,
axisExpandCenter: 15,
axisExpandCount: 10,
axisExpandWidth: 60,
axisExpandTriggerOn: 'mousemove',
z: 100,
parallelAxisDefault: {
type: 'value',
nameLocation: 'start',
nameRotate: 25,
// nameLocation: 'end',
nameTextStyle: {
fontSize: 12
},
nameTruncate: {
maxWidth: 170
},
nameGap: 20,
splitNumber: 3,
tooltip: {
show: true
},
axisLine: {
// show: false,
lineStyle: {
width: 1,
color: '#000000'
}
},
axisTick: {
show: false
},
splitLine: {
show: false
},
z: 100
}
},
series: [
{
name: 'parallel',
type: 'parallel',
smooth: true,
lineStyle: {
color: '#577ceb',
width: 0.5,
opacity: 0.6
},
z: 100,
data: this.rawData
}
]
};
Function:
onChartSelect(e){
console.log(e);
}
Am I using the correct events for doing so? Your help will be much appreciated.
Thanks
according to eCharts document,
the selectDataRange Event emitted after range is changed in visualMap. https://www.echartsjs.com/en/api.html#events.datarangeselected,
which is chartDataRangeSelected of ngx-echarts mapped to.
And you can see that, it is an event related to visualMap. your charts does not have a visual map at all, so i guess the event will not be fired.
You can try chartAxisAreaSelected, as this is more related to your chart.